1
0
mirror of https://github.com/django/django.git synced 2025-07-03 09:19:16 +00:00

newforms-admin: Merged to [5194]

git-svn-id: http://code.djangoproject.com/svn/django/branches/newforms-admin@5195 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Adrian Holovaty 2007-05-12 02:36:05 +00:00
parent 4938c8ea6d
commit 415e84ad53
217 changed files with 21393 additions and 10310 deletions

26
AUTHORS
View File

@ -42,13 +42,17 @@ people who have submitted patches, reported bugs, added translations, helped
answer newbie questions, and generally made Django that much better:
adurdin@gmail.com
alang@bright-green.com
Marty Alchin <gulopine@gamemusic.org>
Daniel Alves Barbosa de Oliveira Vaz <danielvaz@gmail.com>
Andreas
andy@jadedplanet.net
Fabrice Aneche <akh@nobugware.com>
ant9000@netwise.it
David Ascher <http://ascher.ca/>
david@kazserve.org
Arthur <avandorp@gmail.com>
axiak@mit.edu
Jiri Barton
Ned Batchelder <http://www.nedbatchelder.com/>
Shannon -jj Behrens <http://jjinux.blogspot.com/>
@ -66,6 +70,8 @@ answer newbie questions, and generally made Django that much better:
Amit Chakradeo <http://amit.chakradeo.net/>
ChaosKCW
ivan.chelubeev@gmail.com
Bryan Chow <bryan at verdjn dot com>
Michal Chruszcz <troll@pld-linux.org>
Ian Clelland <clelland@gmail.com>
crankycoder@gmail.com
Matt Croydon <http://www.postneo.com/>
@ -78,22 +84,26 @@ answer newbie questions, and generally made Django that much better:
Jason Davies (Esaj) <http://www.jasondavies.com/>
Alex Dedul
deric@monowerks.com
Max Derkachev <mderk@yandex.ru>
dne@mayonnaise.net
Maximillian Dornseif <md@hudora.de>
Jeremy Dunck <http://dunck.us/>
Andy Dustman <farcepest@gmail.com>
Clint Ecker
enlight
Enrico <rico.bl@gmail.com>
Ludvig Ericson <ludvig.ericson@gmail.com>
Dirk Eschler <dirk.eschler@gmx.net>
Marc Fargas <telenieko@telenieko.com>
favo@exoweb.net
Bill Fenner <fenner@gmail.com>
Matthew Flanagan <http://wadofstuff.blogspot.com>
Eric Floehr <eric@intellovations.com>
Jorge Gajon <gajon@gajon.org>
gandalf@owca.info
Baishampayan Ghose
martin.glueck@gmail.com
GomoX <gomo@datafull.com>
Simon Greenhill <dev@simon.net.nz>
Owen Griffiths
Espen Grindhaug <http://grindhaug.org/>
@ -105,11 +115,14 @@ answer newbie questions, and generally made Django that much better:
hipertracker@gmail.com
Ian Holsman <http://feh.holsman.net/>
Kieran Holland <http://www.kieranholland.com>
Sung-Jin Hong <serialx.net@gmail.com>
Robert Rock Howard <http://djangomojo.com/>
Jason Huggins <http://www.jrandolph.com/blog/>
Hyun Mi Ae
Tom Insam
Baurzhan Ismagulov <ibr@radix50.net>
jcrasta@gmail.com
Zak Johnson <zakj@nox.cx>
Michael Josephson <http://www.sdjournal.com/>
jpellerin@gmail.com
junzhang.jn@gmail.com
@ -120,6 +133,8 @@ answer newbie questions, and generally made Django that much better:
Sune Kirkeby <http://ibofobi.dk/>
Bastian Kleineidam <calvin@debian.org>
Cameron Knight (ckknight)
Gasper Koren
Martin Kosír <martin@martinkosir.net>
Meir Kriheli <http://mksoft.co.il/>
Bruce Kroeze <http://coderseye.com/>
Joseph Kocherhans
@ -134,12 +149,13 @@ answer newbie questions, and generally made Django that much better:
lerouxb@gmail.com
Waylan Limberg <waylan@gmail.com>
limodou
mattmcc
Matt McClanahan <http://mmcc.cx/>
Martin Maney <http://www.chipy.org/Martin_Maney>
masonsimon+django@gmail.com
Manuzhai
Petar Marić <http://www.petarmaric.com/>
Nuno Mariz <nmariz@gmail.com>
marijn@metronomo.cl
mark@junklight.com
Yasushi Masuda <whosaysni@gmail.com>
mattycakes@gmail.com
@ -153,6 +169,7 @@ answer newbie questions, and generally made Django that much better:
Robin Munn <http://www.geekforgod.com/>
Robert Myers <myer0052@gmail.com>
Nebojša Dorđević
Gopal Narayanan <gopastro@gmail.com>
Fraser Nevett <mail@nevett.org>
Sam Newman <http://www.magpiebrain.com/>
Neal Norwitz <nnorwitz@google.com>
@ -168,14 +185,19 @@ answer newbie questions, and generally made Django that much better:
Luke Plant <http://lukeplant.me.uk/>
plisk
Daniel Poelzleithner <http://poelzi.org/>
polpak@yahoo.com
J. Rademaker
Michael Radziej <mir@noris.de>
ramiro
Massimiliano Ravelli <massimiliano.ravelli@gmail.com>
Brian Ray <http://brianray.chipy.org/>
remco@diji.biz
rhettg@gmail.com
Henrique Romano <onaiort@gmail.com>
Armin Ronacher
Oliver Rutherfurd <http://rutherfurd.net/>
Ivan Sagalaev (Maniac) <http://www.softwaremaniacs.org/>
Vinay Sajip <vinay_sajip@yahoo.co.uk>
David Schein
scott@staplefish.com
serbaut@gmail.com
@ -199,6 +221,7 @@ answer newbie questions, and generally made Django that much better:
torne-django@wolfpuppy.org.uk
Karen Tracey <graybark@bellsouth.net>
Makoto Tsuyuki <mtsuyuki@gmail.com>
tt@gurgle.no
Amit Upadhyay
Geert Vanderkelen
viestards.lists@gmail.com
@ -206,6 +229,7 @@ answer newbie questions, and generally made Django that much better:
wam-djangobug@wamber.net
Dan Watson <http://theidioteque.net/>
Chris Wesseling <Chris.Wesseling@cwi.nl>
charly.wilhelm@gmail.com
Rachel Willmer <http://www.willmer.com/kb/>
Gary Wilson <gary.wilson@gmail.com>
wojtek

View File

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

View File

@ -81,7 +81,7 @@ def make_messages():
src = pythonize_re.sub('\n#', src)
open(os.path.join(dirpath, '%s.py' % file), "wb").write(src)
thefile = '%s.py' % file
cmd = 'xgettext %s -d %s -L Perl --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy --from-code UTF-8 -o - "%s"' % (
cmd = 'xgettext %s -d %s -L Perl --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy:1,2 --from-code UTF-8 -o - "%s"' % (
os.path.exists(potfile) and '--omit-header' or '', domain, os.path.join(dirpath, thefile))
(stdin, stdout, stderr) = os.popen3(cmd, 'b')
msgs = stdout.read()
@ -103,7 +103,7 @@ def make_messages():
open(os.path.join(dirpath, '%s.py' % file), "wb").write(templatize(src))
thefile = '%s.py' % file
if verbose: sys.stdout.write('processing file %s in %s\n' % (file, dirpath))
cmd = 'xgettext %s -d %s -L Python --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy --from-code UTF-8 -o - "%s"' % (
cmd = 'xgettext %s -d %s -L Python --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy:1,2 --from-code UTF-8 -o - "%s"' % (
os.path.exists(potfile) and '--omit-header' or '', domain, os.path.join(dirpath, thefile))
(stdin, stdout, stderr) = os.popen3(cmd, 'b')
msgs = stdout.read()

View File

@ -22,7 +22,7 @@ def gather_stats(p):
else:
continue
print "Processing %s" % f
if profiles.has_key(path):
if path in profiles:
profiles[path].add(prof)
else:
profiles[path] = prof

View File

@ -55,6 +55,7 @@ LANGUAGES = (
('is', gettext_noop('Icelandic')),
('it', gettext_noop('Italian')),
('ja', gettext_noop('Japanese')),
('ko', gettext_noop('Korean')),
('kn', gettext_noop('Kannada')),
('lv', gettext_noop('Latvian')),
('mk', gettext_noop('Macedonian')),
@ -118,6 +119,7 @@ EMAIL_PORT = 25
# Optional SMTP authentication information for EMAIL_HOST.
EMAIL_HOST_USER = ''
EMAIL_HOST_PASSWORD = ''
EMAIL_USE_TLS = False
# List of strings representing installed apps.
INSTALLED_APPS = ()
@ -311,6 +313,12 @@ BANNED_IPS = ()
AUTHENTICATION_BACKENDS = ('django.contrib.auth.backends.ModelBackend',)
LOGIN_URL = '/accounts/login/'
LOGOUT_URL = '/accounts/logout/'
LOGIN_REDIRECT_URL = '/accounts/profile/'
###########
# TESTING #
###########

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,7 @@ msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2006-05-16 10:13+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: panos laganakos <panos.laganakos@gmail.com>\n"
"Last-Translator: Orestis Markou <orestis@orestis.gr>\n"
"Language-Team: Greek\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
@ -164,9 +164,9 @@ msgid ""
"\n"
"%(text)s"
msgstr ""
"Αυτο το σχόλιο σημειώθηκε απο %(χρήστη)ες\n"
"Αυτο το σχόλιο σημειώθηκε απο %(user)s\n"
"\n"
"%(κείμενο)α"
"%(text)s"
#: contrib/comments/models.py:265
msgid "flag date"

View File

@ -305,7 +305,7 @@ msgstr "Japon
#: conf/global_settings.py:58
msgid "Latvian"
msgstr ""
msgstr "Latvio"
#: conf/global_settings.py:59
msgid "Macedonian"
@ -611,7 +611,7 @@ msgstr "La URL %s no apunta a una imagen v
#, python-format
msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid."
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."
#: 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."
msgstr[0] ""
"Por favor, introduzca un número decimal válido con a lo más %s dígito en "
"total."
"su parte entera."
msgstr[1] ""
"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
#, python-format
@ -958,7 +958,7 @@ msgid ""
"digits and underscores)."
msgstr ""
"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
msgid "first name"
@ -1107,7 +1107,7 @@ msgstr "Las contrase
#: contrib/auth/forms.py:124
msgid "Your old password was entered incorrectly. Please enter it again."
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."
#: contrib/comments/models.py:67 contrib/comments/models.py:166
@ -1707,7 +1707,7 @@ msgid ""
msgstr ""
"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 "
"paciencia"
"paciencia."
#: contrib/admin/templates/admin/search_form.html:8
msgid "Go"
@ -1899,7 +1899,7 @@ msgid ""
"the appropriate user."
msgstr ""
"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."
#: 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 "
"options."
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."
#: contrib/admin/templates/admin/auth/user/add_form.html:12
@ -2105,7 +2105,7 @@ msgstr "vista:"
#: contrib/admin/views/doc.py:164
#, python-format
msgid "App %r not found"
msgstr "Applicación %r no encontrada"
msgstr "Aplicación %r no encontrada"
#: contrib/admin/views/doc.py:171
#, python-format
@ -2326,12 +2326,12 @@ msgstr "Cambiar clave: %s"
#: contrib/localflavor/usa/forms.py:17
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
msgid "Enter a postcode. A space is required between the two postcode parts."
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."
#: contrib/sessions/models.py:51

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -8,26 +8,14 @@ msgid ""
msgstr ""
"Project-Id-Version: djangojs 1.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2006-03-30 13:28+0200\n"
"PO-Revision-Date: 2006-03-30 13:35+0200\n"
"POT-Creation-Date: 2007-05-06 13:08+0300\n"
"PO-Revision-Date: 2007-05-06 13:08+0300\n"
"Last-Translator: Meir Kriheli <meir@mksoft.co.il>\n"
"Language-Team: Hebrew\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit"
#: contrib/admin/media/js/dateparse.js:32
#: contrib/admin/media/js/calendar.js:24
msgid ""
"January February March April May June July August September October November "
"December"
msgstr ""
"ינואר פברואר מרץ אפריל מאי יוני יולי אוגוסט ספטמבר אוקטובר נובמבר דצמבר"
#: contrib/admin/media/js/dateparse.js:33
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
msgstr "ראשון שני שלישי רביעי חמישי שישי שבת"
#: contrib/admin/media/js/SelectFilter2.js:33
#, perl-format
msgid "Available %s"
@ -58,54 +46,75 @@ msgstr "יש לסמן את ההרשאות המבוקשות וללחוץ על "
msgid "Clear all"
msgstr "איפוס הכל"
#: 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 ""
"ינואר פברואר מרץ אפריל מאי יוני יולי אוגוסט ספטמבר אוקטובר נובמבר דצמבר"
#: contrib/admin/media/js/calendar.js:25
msgid "S M T W T F S"
msgstr "ר ש ש ר ח ש ש"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80
#: contrib/admin/media/js/dateparse.js:33
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
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:48
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:51
msgid "Clock"
msgstr "שעון"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:77
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:78
msgid "Choose a time"
msgstr "בחירת שעה"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
msgid "Midnight"
msgstr "חצות"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
msgid "6 a.m."
msgstr "6 בבוקר"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:84
msgid "Noon"
msgstr "צהריים"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:87
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:168
#: 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:111
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:162
#: 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:114
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:132
msgid "Calendar"
msgstr "לוח שנה"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:160
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:175
msgid "Yesterday"
msgstr "אתמול"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
msgid "Tomorrow"
msgstr "מחר"

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,7 @@ msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2007-02-15 10:46+1100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Last-Translator: Gatis Tomsons <gatis.tomsons@gmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
@ -19,64 +19,65 @@ msgstr ""
#: contrib/admin/media/js/SelectFilter2.js:33
#, perl-format
msgid "Available %s"
msgstr ""
msgstr "Pieejams %s"
#: contrib/admin/media/js/SelectFilter2.js:41
msgid "Choose all"
msgstr ""
msgstr "Izvēlēties visu"
#: contrib/admin/media/js/SelectFilter2.js:46
msgid "Add"
msgstr ""
msgstr "Pievienot"
#: contrib/admin/media/js/SelectFilter2.js:48
msgid "Remove"
msgstr ""
msgstr "Izņemt"
#: contrib/admin/media/js/SelectFilter2.js:53
#, perl-format
msgid "Chosen %s"
msgstr ""
msgstr "Izvēlies %s"
#: contrib/admin/media/js/SelectFilter2.js:54
msgid "Select your choice(s) and click "
msgstr ""
msgstr "Izvēlies un klikšķini"
#: contrib/admin/media/js/SelectFilter2.js:59
msgid "Clear all"
msgstr ""
msgstr "Attīrīt visu"
#: contrib/admin/media/js/dateparse.js:32
#: contrib/admin/media/js/calendar.js:24
msgid ""
"January February March April May June July August September October November "
"December"
msgstr ""
msgstr "Janvāris Februāris Marts Aprīlis Maijs Jūnijs Jūlijs Augusts Septembris Oktobris Novembris"
"Decembris"
#: contrib/admin/media/js/dateparse.js:33
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
msgstr ""
msgstr "Svētdiena Pirmdiena Otrdiena Trešdiena Ceturtdiena Piektdiena Sestdiena"
#: contrib/admin/media/js/calendar.js:25
msgid "S M T W T F S"
msgstr ""
msgstr "S M T W T F S"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:47
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
msgid "Now"
msgstr ""
msgstr "Tagad"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:51
msgid "Clock"
msgstr ""
msgstr "Pulkstens"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:78
msgid "Choose a time"
msgstr ""
msgstr "Izvēlieties laiku"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
msgid "Midnight"
msgstr ""
msgstr "Pusnakts"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
msgid "6 a.m."
@ -84,35 +85,35 @@ msgstr ""
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:84
msgid "Noon"
msgstr ""
msgstr "Pusdienas laiks"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:88
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
msgid "Cancel"
msgstr ""
msgstr "Atcelt"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:128
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:177
msgid "Today"
msgstr ""
msgstr "Šodien"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:132
msgid "Calendar"
msgstr ""
msgstr "Kalendārs"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:175
msgid "Yesterday"
msgstr ""
msgstr "Vakar"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
msgid "Tomorrow"
msgstr ""
msgstr "Rīt"
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:34
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:72
msgid "Show"
msgstr ""
msgstr "Parādīt"
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:63
msgid "Hide"
msgstr ""
msgstr "Slēpt"

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
# SOME DESCRIPTIVE TITLE.
# translation of django.po to
# Copyright (C) 2005 and beyond
# This file is distributed under the same license as the PACKAGE package.
# Espen Grindhaug <espen@grindhaug.org>, Nov 2005.
@ -6,74 +6,73 @@
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Project-Id-Version: django\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2006-05-16 10:12+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Espen Grndhaug <espen@grindhaug.org>\n"
"Language-Team: Norwegian\n"
"PO-Revision-Date: 2007-04-27 06:48+0200\n"
"Last-Translator: \n"
"Language-Team: <en@li.org>\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"
"X-Generator: KBabel 1.11.4\n"
#: contrib/comments/models.py:67 contrib/comments/models.py:166
#, fuzzy
msgid "object ID"
msgstr "Vis objekt ID"
msgstr "objekt ID"
#: contrib/comments/models.py:68
msgid "headline"
msgstr ""
msgstr "overskrift"
#: contrib/comments/models.py:69 contrib/comments/models.py:90
#: contrib/comments/models.py:167
#, fuzzy
msgid "comment"
msgstr "innhold"
msgstr "kommentar"
#: contrib/comments/models.py:70
msgid "rating #1"
msgstr ""
msgstr "rangering #1 "
#: contrib/comments/models.py:71
msgid "rating #2"
msgstr ""
msgstr "rangering #2"
#: contrib/comments/models.py:72
msgid "rating #3"
msgstr ""
msgstr "rangering #3"
#: contrib/comments/models.py:73
msgid "rating #4"
msgstr ""
msgstr "rangering #4"
#: contrib/comments/models.py:74
msgid "rating #5"
msgstr ""
msgstr "rangering #5"
#: contrib/comments/models.py:75
msgid "rating #6"
msgstr ""
msgstr "rangering #6"
#: contrib/comments/models.py:76
msgid "rating #7"
msgstr ""
msgstr "rangering #7"
#: contrib/comments/models.py:77
msgid "rating #8"
msgstr ""
msgstr "rangering #8"
#: contrib/comments/models.py:82
msgid "is valid rating"
msgstr ""
msgstr "er gyldig rangering"
#: contrib/comments/models.py:83 contrib/comments/models.py:169
msgid "date/time submitted"
msgstr ""
msgstr "dato/tid for innsendelse"
#: contrib/comments/models.py:84 contrib/comments/models.py:170
msgid "is public"
msgstr ""
msgstr "er tilgjengelig for alle"
#: contrib/comments/models.py:85 contrib/admin/views/doc.py:289
msgid "IP address"
@ -81,23 +80,21 @@ msgstr "IP adresse"
#: contrib/comments/models.py:86
msgid "is removed"
msgstr ""
msgstr "er fjernet"
#: contrib/comments/models.py:86
msgid ""
"Check this box if the comment is inappropriate. A \"This comment has been "
"removed\" message will be displayed instead."
msgstr ""
msgstr "Aktiver denne avkryssningsboksen hvis kommentaren er upasende. Beskjeden \"Denne kommentaren er blitt fjernet\" vil bli vist istedet."
#: contrib/comments/models.py:91
#, fuzzy
msgid "comments"
msgstr "innhold"
msgstr "kommentarer"
#: contrib/comments/models.py:131 contrib/comments/models.py:207
#, fuzzy
msgid "Content object"
msgstr "innholds type"
msgstr "innholdsobjekt"
#: contrib/comments/models.py:159
#, python-format
@ -108,101 +105,97 @@ msgid ""
"\n"
"http://%(domain)s%(url)s"
msgstr ""
"Sendt av %(user)s på %(date)s\n"
"\n"
"%(comment)s\n"
"\n"
"http://%(domain)s%(url)s"
#: contrib/comments/models.py:168
#, fuzzy
msgid "person's name"
msgstr "fornavn"
msgstr "personens navn"
#: contrib/comments/models.py:171
#, fuzzy
msgid "ip address"
msgstr "IP adresse"
#: contrib/comments/models.py:173
msgid "approved by staff"
msgstr ""
msgstr "godkjent av moderator"
#: contrib/comments/models.py:176
#, fuzzy
msgid "free comment"
msgstr "tillat kommentarer"
msgstr "åpen kommentar"
#: contrib/comments/models.py:177
#, fuzzy
msgid "free comments"
msgstr "tillat kommentarer"
msgstr "åpne kommentarer"
#: contrib/comments/models.py:233
msgid "score"
msgstr ""
msgstr "poeng"
#: contrib/comments/models.py:234
#, fuzzy
msgid "score date"
msgstr "utløpsdato"
msgstr "poeng dato"
#: contrib/comments/models.py:237
msgid "karma score"
msgstr ""
msgstr "karma poeng"
#: contrib/comments/models.py:238
msgid "karma scores"
msgstr ""
msgstr "karma poeng"
#: contrib/comments/models.py:242
#, python-format
msgid "%(score)d rating by %(user)s"
msgstr ""
msgstr "%(score)d rangering av %(user)s"
#: contrib/comments/models.py:258
#, fuzzy, python-format
#, python-format
msgid ""
"This comment was flagged by %(user)s:\n"
"\n"
"%(text)s"
msgstr ""
"Denne kommentaren er skrevet med lite omtanke:\n"
"Denne kommentaren er flagget av %(user)s:\n"
"\n"
"%(text)s"
#: contrib/comments/models.py:265
#, fuzzy
msgid "flag date"
msgstr "flatside"
msgstr "flagg dato"
#: contrib/comments/models.py:268
#, fuzzy
msgid "user flag"
msgstr "Bruker"
msgstr "brukerflag"
#: contrib/comments/models.py:269
#, fuzzy
msgid "user flags"
msgstr "Brukere"
msgstr "brukerflag"
#: contrib/comments/models.py:273
#, python-format
msgid "Flag by %r"
msgstr ""
msgstr "Flagg med %r"
#: contrib/comments/models.py:278
#, fuzzy
msgid "deletion date"
msgstr "sesjon data"
msgstr "fjernet dato"
#: contrib/comments/models.py:280
msgid "moderator deletion"
msgstr ""
msgstr "fjernet av moderator"
#: contrib/comments/models.py:281
msgid "moderator deletions"
msgstr ""
msgstr "fjernet av moderator"
#: contrib/comments/models.py:285
#, python-format
msgid "Moderator deletion by %r"
msgstr ""
msgstr "Fjernet av moderator med %r"
#: contrib/comments/views/karma.py:19
msgid "Anonymous users cannot vote"
@ -214,16 +207,14 @@ msgstr "Ikke gyldig kommentar ID"
#: contrib/comments/views/karma.py:25
msgid "No voting for yourself"
msgstr "Du kan ikke stemme selv"
msgstr "Du kan ikke stemme på deg selv"
#: contrib/comments/views/comments.py:28
#, fuzzy
msgid ""
"This rating is required because you've entered at least one other rating."
msgstr "Denne bla bla.."
msgid "This rating is required because you've entered at least one other rating."
msgstr "Denne rangeringen er påkrevd fordi du har rangert en eller flere ting fra før "
#: contrib/comments/views/comments.py:112
#, fuzzy, python-format
#, python-format
msgid ""
"This comment was posted by a user who has posted fewer than %(count)s "
"comment:\n"
@ -246,13 +237,13 @@ msgstr[1] ""
"%(text)s"
#: contrib/comments/views/comments.py:117
#, fuzzy, python-format
#, python-format
msgid ""
"This comment was posted by a sketchy user:\n"
"\n"
"%(text)s"
msgstr ""
"Denne kommentaren er skrevet med lite omtanke:\n"
"Denne kommentaren er skrevet av en upålitelig bruker:\n"
"\n"
"%(text)s"
@ -281,8 +272,7 @@ msgstr "Skjemaet hadde en ugyldig verdi - objekt IDen var ugyldig"
#: contrib/comments/views/comments.py:257
#: contrib/comments/views/comments.py:321
msgid "The comment form didn't provide either 'preview' or 'post'"
msgstr ""
"Kommentar skjemaet returnerte ikke et 'forhåndsvisning' eller 'post' objekt"
msgstr "Kommentar skjemaet returnerte ikke et 'forhåndsvisning' eller 'post' objekt"
#: contrib/comments/templates/comments/form.html:6
#: contrib/comments/templates/comments/form.html:8
@ -296,9 +286,8 @@ msgid "Password:"
msgstr "Passord:"
#: contrib/comments/templates/comments/form.html:6
#, fuzzy
msgid "Forgotten your password?"
msgstr "Endre passord"
msgstr "Har du glemt passordet ditt ?"
#: contrib/comments/templates/comments/form.html:8
#: contrib/admin/templates/admin/object_history.html:3
@ -323,38 +312,35 @@ msgstr "Log ut"
#: contrib/comments/templates/comments/form.html:12
msgid "Ratings"
msgstr ""
msgstr "Rangeringer"
#: contrib/comments/templates/comments/form.html:12
#: contrib/comments/templates/comments/form.html:23
msgid "Required"
msgstr ""
msgstr "Påkrevd"
#: contrib/comments/templates/comments/form.html:12
#: contrib/comments/templates/comments/form.html:23
msgid "Optional"
msgstr ""
msgstr "Valgfri"
#: contrib/comments/templates/comments/form.html:23
msgid "Post a photo"
msgstr ""
msgstr "Send et foto"
#: contrib/comments/templates/comments/form.html:27
#: contrib/comments/templates/comments/freeform.html:5
#, fuzzy
msgid "Comment:"
msgstr "tillat kommentarer"
msgstr "Kommentar:"
#: contrib/comments/templates/comments/form.html:32
#: contrib/comments/templates/comments/freeform.html:9
#, fuzzy
msgid "Preview comment"
msgstr "tillat kommentarer"
msgstr "Forhåndvis kommentar"
#: contrib/comments/templates/comments/freeform.html:4
#, fuzzy
msgid "Your name:"
msgstr "brukernavn"
msgstr "Ditt navn:"
#: contrib/admin/filterspecs.py:40
#, python-format
@ -416,7 +402,7 @@ msgstr "objekt repr"
#: contrib/admin/models.py:21
msgid "action flag"
msgstr "handlings flagg"
msgstr "handlingsflagg"
#: contrib/admin/models.py:22
msgid "change message"
@ -424,11 +410,11 @@ msgstr "endre melding"
#: contrib/admin/models.py:25
msgid "log entry"
msgstr "logg notis"
msgstr "logg post"
#: contrib/admin/models.py:26
msgid "log entries"
msgstr "logg innlegg"
msgstr "logg poster"
#: contrib/admin/templatetags/admin_list.py:228
msgid "All dates"
@ -440,8 +426,8 @@ msgid ""
"Please enter a correct username and password. Note that both fields are case-"
"sensitive."
msgstr ""
"Vær snill å angi korrekt brukernavn og passord. La merke til at små og "
"store bokstaver er betraktet ulik."
"Vennligst angi korrekt brukernavn og passord. Merk at små og "
"store bokstaver er betraktet ulikt."
#: contrib/admin/views/decorators.py:23
#: contrib/admin/templates/admin/login.html:25
@ -452,18 +438,15 @@ msgstr "Logg inn"
msgid ""
"Please log in again, because your session has expired. Don't worry: Your "
"submission has been saved."
msgstr ""
"Du må logge inn igjen, fordi sesjonen din har gått ut på dato, men ikke ikke "
"bekjymr deg informasjonen du sendte ble lagret."
msgstr "Du må logge inn igjen, fordi økten din har gått ut, men innlegget ditt ble lagret."
#: contrib/admin/views/decorators.py:68
msgid ""
"Looks like your browser isn't configured to accept cookies. Please enable "
"cookies, reload this page, and try again."
msgstr ""
"Det ser ut som om nettleseren din ikke vill ta i mot informasjonskapsler "
"('cookies'). Vennligst omkonfigurer nettleseren din, last siden på ny og "
"prøv igjen."
"Det ser ut som om nettleseren din ikke støtter informasjonskapsler "
"('cookies'). Vennligst konfigurer nettleseren din, og prøv igjen."
#: contrib/admin/views/decorators.py:82
msgid "Usernames cannot contain the '@' character."
@ -500,7 +483,7 @@ msgstr "Ny %s"
#: contrib/admin/views/main.py:336
#, python-format
msgid "Added %s."
msgstr "Lagt til %s"
msgstr "La til %s"
#: contrib/admin/views/main.py:336 contrib/admin/views/main.py:338
#: contrib/admin/views/main.py:340
@ -528,8 +511,7 @@ msgstr "%(name)s \"%(obj)s\" ble endret."
#: contrib/admin/views/main.py:354
#, python-format
msgid ""
"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
msgid "The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
msgstr "%(name)s \"%(obj)s\" ble endret. Du kan endre det igjen under."
#: contrib/admin/views/main.py:392
@ -742,8 +724,8 @@ msgid ""
"There's been an error. It's been reported to the site administrators via e-"
"mail and should be fixed shortly. Thanks for your patience."
msgstr ""
"Det har vært en feil. Feilen er blitt rapportert til administrator via e-"
"mail, og vill bli fikset snart. Takk for din tålmodighet."
"Det har oppstått en feil. Feilen er blitt rapportert til administrator via e-"
"post, og vil bli fikset snart. Takk for din tålmodighet."
#: contrib/admin/templates/admin/404.html:4
#: contrib/admin/templates/admin/404.html:8
@ -909,7 +891,7 @@ msgstr "Tilbakestill mitt passord"
#: contrib/admin/templates/registration/logged_out.html:8
msgid "Thanks for spending some quality time with the Web site today."
msgstr "Takk for å bruke tid på internett siden i dag."
msgstr "Takk for at du valgte å bruke kvalitetstid på nettstedet idag."
#: contrib/admin/templates/registration/logged_out.html:10
msgid "Log in again"
@ -954,8 +936,7 @@ msgstr "Endre passord"
#: contrib/admin/templates/registration/password_reset_email.html:2
msgid "You're receiving this e-mail because you requested a password reset"
msgstr ""
"Du har mottatt denne e-posten fordi du ba om å tilbakestille passordet ditt"
msgstr "Du har mottatt denne e-posten fordi du ba om å tilbakestille passordet ditt"
#: contrib/admin/templates/registration/password_reset_email.html:3
#, python-format
@ -1002,6 +983,12 @@ msgid ""
"as \"internal\" (talk to your system administrator if you aren't sure if\n"
"your computer is \"internal\").</p>\n"
msgstr ""
"\n"
"<p class=\"help\">For å installere bokmerker, dra linken til verktøylinja\n"
"for bokmerker, eller høyreklikk og legg til i bokmerker. Nå kan du du velge\n"
"bokmerket fra hvilken som helst side på nettstedet. Noen av disse\n"
"bokmerkene krever at datamaskinen du bruker er markert som \"intern\"\n"
"(kontakt din systemadministrator hvis du er usikker på om maskinen din er \"intern\").</p>\n"
#: contrib/admin/templates/admin_doc/bookmarklets.html:19
msgid "Documentation for this page"
@ -1033,8 +1020,7 @@ msgstr "Endre dette objektet (åpnes i dette vinduet)"
#: contrib/admin/templates/admin_doc/bookmarklets.html:26
msgid "Jumps to the admin page for pages that represent a single object."
msgstr ""
"Hopp til administrasjonsiden for sidene som representerer et enkelt objekt."
msgstr "Hopp til administrasjonsiden for sidene som representerer et enkelt objekt."
#: contrib/admin/templates/admin_doc/bookmarklets.html:28
msgid "Edit this object (new window)"
@ -1069,7 +1055,7 @@ msgid ""
"This should be an absolute path, excluding the domain name. Example: '/"
"events/search/'."
msgstr ""
"Denne burde vær en fullstendig sti, uten domene navnet. Foreksempel: '/"
"Dette burde vært en fullstendig sti, uten domene navnet. Foreksempel: '/"
"nyheter/les/"
#: contrib/redirects/models.py:9
@ -1081,7 +1067,7 @@ msgid ""
"This can be either an absolute path (as above) or a full URL starting with "
"'http://'."
msgstr ""
"Denne kan enten være en fullstendig sti (som over), eller en hel "
"Dette kan enten være en fullstendig sti (som over), eller en hel "
"internettadresse som starter med 'http://'"
#: contrib/redirects/models.py:12
@ -1093,10 +1079,8 @@ msgid "redirects"
msgstr "omadresserelser"
#: contrib/flatpages/models.py:8
msgid ""
"Example: '/about/contact/'. Make sure to have leading and trailing slashes."
msgstr ""
"Eksempel: '/om/kontakt/'. Vær sikker på at du har en skråstrek forran og bak."
msgid "Example: '/about/contact/'. Make sure to have leading and trailing slashes."
msgstr "Eksempel: '/om/kontakt/'. Vær sikker på at du har en skråstrek forran og bak."
#: contrib/flatpages/models.py:9
msgid "title"
@ -1186,7 +1170,7 @@ msgstr "passord"
#: contrib/auth/models.py:59
msgid "Use '[algo]$[salt]$[hexdigest]'"
msgstr ""
msgstr "Bruk '[algo]$[salt]$[hexdigest]'"
#: contrib/auth/models.py:60
msgid "staff status"
@ -1256,7 +1240,7 @@ msgstr "Melding"
msgid ""
"Your Web browser doesn't appear to have cookies enabled. Cookies are "
"required for logging in."
msgstr ""
msgstr "Din nettleser ser ikkeut til å støtte informasjonskapsler (cookies). Informasjonskapsler er påkrevd for å logge inn."
#: contrib/contenttypes/models.py:25
msgid "python model class name"
@ -1698,8 +1682,7 @@ msgstr "Internettadressen %s peker ikke til et godkjent bilde."
#: core/validators.py:159
#, python-format
msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid."
msgstr ""
"Telefon nummeret må være i XXX-XXX-XXXX format. \"%s\" er ikke godkjent."
msgstr "Telefon nummeret må være i XXX-XXX-XXXX format. \"%s\" er ikke godkjent."
#: core/validators.py:167
#, python-format
@ -1732,7 +1715,7 @@ msgstr "Ikke godkjent URL: %s"
#: core/validators.py:206 core/validators.py:208
#, python-format
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
msgid "Enter a valid U.S. state abbreviation."
@ -1784,30 +1767,26 @@ msgstr "Vennligst skriv inn et godkjent desimal tall."
#: core/validators.py:349
#, python-format
msgid "Please enter a valid decimal number with at most %s total digit."
msgid_plural ""
"Please enter a valid decimal number with at most %s total digits."
msgid_plural "Please enter a valid decimal number with at most %s total digits."
msgstr[0] "Skriv inn et desimal tall med maksimum %s total antall tall."
msgstr[1] "Skriv inn et desimal tall med maksimum %s total antall tall."
#: core/validators.py:352
#, python-format
msgid "Please enter a valid decimal number with at most %s decimal place."
msgid_plural ""
"Please enter a valid decimal number with at most %s decimal places."
msgid_plural "Please enter a valid decimal number with at most %s decimal places."
msgstr[0] "Skriv inn et desimal tall med maksimum %s tall bak komma. "
msgstr[1] "Skriv inn et desimal tall med maksimum %s tall bak komma. "
#: core/validators.py:362
#, python-format
msgid "Make sure your uploaded file is at least %s bytes big."
msgstr ""
"Vær sikker på at fila du prøver å laste opp er minimum %s bytes stor."
msgstr "Vær sikker på at fila du prøver å laste opp er minimum %s bytes stor."
#: core/validators.py:363
#, python-format
msgid "Make sure your uploaded file is at most %s bytes big."
msgstr ""
"Vær sikker på at fila du prøver å laste opp er maksimum %s bytes stor."
msgstr "Vær sikker på at fila du prøver å laste opp er maksimum %s bytes stor."
#: core/validators.py:376
msgid "The format for this field is wrong."
@ -1824,8 +1803,7 @@ msgstr "Klarte ikke å motta noe fra %s."
#: core/validators.py:429
#, python-format
msgid ""
"The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
msgid "The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
msgstr ""
"Internettadressen %(url)s returnerte en ikke godkjent Content-Type '%"
"(contenttype)s'."
@ -1881,7 +1859,7 @@ msgid ""
"The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line "
"starts with \"%(start)s\".)"
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\".)"
#: db/models/manipulators.py:302
@ -1892,7 +1870,7 @@ msgstr "%(object)s med %(type)s finnes allerede for angitt %(field)s."
#: db/models/fields/__init__.py:40
#, python-format
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:542 db/models/fields/__init__.py:553
@ -1926,16 +1904,13 @@ msgid "Separate multiple IDs with commas."
msgstr "Separer Id-ene med kommaer."
#: db/models/fields/related.py:581
msgid ""
"Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
msgstr ""
"Hold nede \"Control\", eller \"Command\" på en Mac, for å velge mere enn en."
msgid "Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
msgstr "Hold nede \"Control\", eller \"Command\" på en Mac, for å velge mere enn en."
#: db/models/fields/related.py:625
#, python-format
msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid."
msgid_plural ""
"Please enter valid %(self)s IDs. The values %(value)r are invalid."
msgid_plural "Please enter valid %(self)s IDs. The values %(value)r are invalid."
msgstr[0] "Skriv inn gyldige %(self)s ID-er. Verdien %(value)r er ikke gyldig."
msgstr[1] "Skriv inn gyldige %(self)s ID-er. Verdiene %(value)r er ikke gyldige."

View File

@ -1,19 +1,20 @@
# SOME DESCRIPTIVE TITLE.
# translation of djangojs.po to
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# Espen Grindhaug <espen.grindhaug@mail.com>, 2006.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Project-Id-Version: djangojs\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2005-12-09 11:51+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Espen Grindhaug <espen.grindhaug@gmail.com>\n"
"Language-Team: no\n"
"PO-Revision-Date: 2007-04-27 06:51+0200\n"
"Last-Translator: \n"
"Language-Team: <en@li.org>\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"
"X-Generator: KBabel 1.11.4\n"
#: contrib/admin/media/js/SelectFilter2.js:33
#, perl-format
@ -21,7 +22,6 @@ msgid "Available %s"
msgstr "%s er tilgjengelige"
#: contrib/admin/media/js/SelectFilter2.js:41
#, fuzzy
msgid "Choose all"
msgstr "Velg alle"
@ -116,3 +116,4 @@ msgstr "I går"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164
msgid "Tomorrow"
msgstr "I morgen"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,20 +1,15 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# VLADO LABATH <vlado@labath.org>, 2005.
#
#, fuzzy
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Project-Id-Version: Django 1.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2005-12-18 19:38-0500\n"
"PO-Revision-Date: 2005-12-18 19:26-0500\n"
"Last-Translator: VLADO LABATH <vlado@labath.org>\n"
"Language-Team: LANGUAGE <sk@li.org>\n"
"POT-Creation-Date: 2007-04-01 19:21+0200\n"
"PO-Revision-Date: 2007-04-03 21:48+0200\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit"
#: contrib/admin/media/js/SelectFilter2.js:33
#, perl-format
@ -23,15 +18,15 @@ msgstr "Možný %s"
#: contrib/admin/media/js/SelectFilter2.js:41
msgid "Choose all"
msgstr "Vyber všetko"
msgstr "Vybr všetko"
#: contrib/admin/media/js/SelectFilter2.js:46
msgid "Add"
msgstr "Pridaj"
msgstr "Pridať"
#: contrib/admin/media/js/SelectFilter2.js:48
msgid "Remove"
msgstr "Vymaž"
msgstr "Vymazať"
#: contrib/admin/media/js/SelectFilter2.js:53
#, perl-format
@ -40,13 +35,13 @@ msgstr "Vybrané %s"
#: contrib/admin/media/js/SelectFilter2.js:54
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
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
msgid ""
"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 "
"December"
#: contrib/admin/media/js/dateparse.js:27
#: contrib/admin/media/js/dateparse.js:33
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
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"
msgstr "N P U S Š P S"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:34
#: 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"
msgstr "Práve teraz"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:48
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:51
msgid "Clock"
msgstr "Hodiny"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:77
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:78
msgid "Choose a time"
msgstr "Vyber čas"
msgstr "Vybr čas"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
msgid "Midnight"
msgstr "Polnoc"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
msgid "6 a.m."
msgstr "6 ráno"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:84
msgid "Noon"
msgstr "Poludnie"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:87
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:168
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:88
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
msgid "Cancel"
msgstr "Zruš"
msgstr "Zruš"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:111
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:162
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:128
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:177
msgid "Today"
msgstr "Dnes"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:114
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:132
msgid "Calendar"
msgstr "Kalendár"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:160
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:175
msgid "Yesterday"
msgstr "Včera"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
msgid "Tomorrow"
msgstr "Zajtra"

Binary file not shown.

View File

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

View File

@ -1344,7 +1344,7 @@ msgstr "四月"
#: utils/dates.py:19
msgid "may"
msgstr "月"
msgstr "月"
#: utils/dates.py:19
msgid "jun"

View File

@ -46,7 +46,7 @@ msgstr "清除全部"
#: contrib/admin/media/js/dateparse.js:32
#: contrib/admin/media/js/calendar.js:24
msgid "January February March April May June July August September October November December"
msgstr "一月 二月 三月 四月 五月 六月 六月 七月 八月 九月 十月 十一月 十二月"
msgstr "一月 二月 三月 四月 五月 六月 七月 八月 九月 十月 十一月 十二月"
#: contrib/admin/media/js/dateparse.js:33
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"

View File

@ -11,9 +11,10 @@ def patterns(prefix, *args):
pattern_list = []
for t in args:
if isinstance(t, (list, tuple)):
pattern_list.append(url(prefix=prefix, *t))
else:
pattern_list.append(t)
t = url(prefix=prefix, *t)
elif isinstance(t, RegexURLPattern):
t.add_prefix(prefix)
pattern_list.append(t)
return pattern_list
def url(regex, view, kwargs=None, name=None, prefix=''):
@ -21,5 +22,7 @@ def url(regex, view, kwargs=None, name=None, prefix=''):
# For include(...) processing.
return RegexURLResolver(regex, view[0], kwargs)
else:
return RegexURLPattern(regex, prefix and (prefix + '.' + view) or view, kwargs, name)
if prefix and isinstance(view, basestring):
view = prefix + '.' + view
return RegexURLPattern(regex, view, kwargs, name)

View File

@ -26,7 +26,7 @@ form .aligned p, form .aligned ul { margin-left:7em; padding-left:30px; }
form .aligned table p { margin-left:0; padding-left:0; }
form .aligned p.help { padding-left:38px; }
.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; }
/* WIDE FIELDSETS */

View File

@ -42,7 +42,7 @@ class FieldWidgetNode(template.Node):
self.bound_field_var = bound_field_var
def get_nodelist(cls, klass):
if not cls.nodelists.has_key(klass):
if klass not in cls.nodelists:
try:
field_class_name = klass.__name__
template_name = "widget/%s.html" % class_name_to_underscored(field_class_name)

View File

@ -11,9 +11,12 @@ class AdminLogNode(template.Node):
return "<GetAdminLog Node>"
def render(self, context):
if self.user is not None and not self.user.isdigit():
self.user = context[self.user].id
context[self.varname] = LogEntry.objects.filter(user__id__exact=self.user).select_related()[:self.limit]
if self.user is None:
context[self.varname] = LogEntry.objects.all().select_related()[:self.limit]
else:
if not self.user.isdigit():
self.user = context[self.user].id
context[self.varname] = LogEntry.objects.filter(user__id__exact=self.user).select_related()[:self.limit]
return ''
class DoGetAdminLog:

View File

@ -17,7 +17,7 @@ def user_add_stage(request):
if not errors:
new_user = manipulator.save(new_data)
msg = _('The %(name)s "%(obj)s" was added successfully.') % {'name': 'user', 'obj': new_user}
if request.POST.has_key("_addanother"):
if "_addanother" in request.POST:
request.user.message_set.create(message=msg)
return HttpResponseRedirect(request.path)
else:
@ -29,7 +29,7 @@ def user_add_stage(request):
return render_to_response('admin/auth/user/add_form.html', {
'title': _('Add user'),
'form': form,
'is_popup': request.REQUEST.has_key('_popup'),
'is_popup': '_popup' in request.REQUEST,
'add': True,
'change': False,
'has_delete_permission': False,
@ -61,7 +61,7 @@ def user_change_password(request, id):
return render_to_response('admin/auth/user/change_password.html', {
'title': _('Change password: %s') % escape(user.username),
'form': form,
'is_popup': request.REQUEST.has_key('_popup'),
'is_popup': '_popup' in request.REQUEST,
'add': True,
'change': False,
'has_delete_permission': False,

View File

@ -12,7 +12,7 @@ LOGIN_FORM_KEY = 'this_is_the_login_form'
def _display_login_form(request, error_message=''):
request.session.set_test_cookie()
if request.POST and request.POST.has_key('post_data'):
if request.POST and 'post_data' in request.POST:
# User has failed login BUT has previously saved post data.
post_data = request.POST['post_data']
elif request.POST:
@ -48,7 +48,7 @@ def staff_member_required(view_func):
def _checklogin(request, *args, **kwargs):
if request.user.is_authenticated() and request.user.is_staff:
# The user is valid. Continue to the admin page.
if request.POST.has_key('post_data'):
if 'post_data' in request.POST:
# User must have re-authenticated through a different window
# or tab.
request.POST = _decode_post_data(request.POST['post_data'])
@ -57,7 +57,7 @@ def staff_member_required(view_func):
assert hasattr(request, 'session'), "The Django admin requires session middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.sessions.middleware.SessionMiddleware'."
# If this isn't already the login page, display it.
if not request.POST.has_key(LOGIN_FORM_KEY):
if LOGIN_FORM_KEY not in request.POST:
if request.POST:
message = _("Please log in again, because your session has expired. Don't worry: Your submission has been saved.")
else:
@ -90,11 +90,9 @@ def staff_member_required(view_func):
if user.is_active and user.is_staff:
login(request, user)
# TODO: set last_login with an event.
user.last_login = datetime.datetime.now()
user.save()
if request.POST.has_key('post_data'):
if 'post_data' in request.POST:
post_data = _decode_post_data(request.POST['post_data'])
if post_data and not post_data.has_key(LOGIN_FORM_KEY):
if post_data and LOGIN_FORM_KEY not in post_data:
# overwrite request.POST with the saved post_data, and continue
request.POST = post_data
request.user = user

View File

@ -200,7 +200,7 @@ def _get_deleted_objects(deleted_objects, perms_needed, user, obj, opts, current
opts_seen.append(related.opts)
rel_opts_name = related.get_accessor_name()
has_related_objs = False
# related.get_accessor_name() could return None for symmetrical relationships
if rel_opts_name:
rel_objs = getattr(obj, rel_opts_name, None)
@ -247,12 +247,12 @@ class ChangeList(object):
self.page_num = int(request.GET.get(PAGE_VAR, 0))
except ValueError:
self.page_num = 0
self.show_all = request.GET.has_key(ALL_VAR)
self.is_popup = request.GET.has_key(IS_POPUP_VAR)
self.show_all = ALL_VAR in request.GET
self.is_popup = IS_POPUP_VAR in request.GET
self.params = dict(request.GET.items())
if self.params.has_key(PAGE_VAR):
if PAGE_VAR in self.params:
del self.params[PAGE_VAR]
if self.params.has_key(ERROR_FLAG):
if ERROR_FLAG in self.params:
del self.params[ERROR_FLAG]
self.order_field, self.order_type = self.get_ordering()
@ -282,7 +282,7 @@ class ChangeList(object):
if k.startswith(r):
del p[k]
for k, v in new_params.items():
if p.has_key(k) and v is None:
if k in p and v is None:
del p[k]
elif v is not None:
p[k] = v
@ -344,7 +344,7 @@ class ChangeList(object):
order_field, order_type = ordering[0][1:], 'desc'
else:
order_field, order_type = ordering[0], 'asc'
if params.has_key(ORDER_VAR):
if ORDER_VAR in params:
try:
field_name = self.list_display[int(params[ORDER_VAR])]
try:
@ -362,7 +362,7 @@ class ChangeList(object):
order_field = f.name
except (IndexError, ValueError):
pass # Invalid ordering specified. Just use the default.
if params.has_key(ORDER_TYPE_VAR) and params[ORDER_TYPE_VAR] in ('asc', 'desc'):
if ORDER_TYPE_VAR in params and params[ORDER_TYPE_VAR] in ('asc', 'desc'):
order_type = params[ORDER_TYPE_VAR]
return order_field, order_type
@ -370,7 +370,7 @@ class ChangeList(object):
qs = self.root_query_set
lookup_params = self.params.copy() # a dictionary of the query string
for i in (ALL_VAR, ORDER_VAR, ORDER_TYPE_VAR, SEARCH_VAR, IS_POPUP_VAR):
if lookup_params.has_key(i):
if i in lookup_params:
del lookup_params[i]
# Apply lookup parameters from the query string.

View File

@ -1,8 +1,8 @@
import datetime
from django.core.exceptions import ImproperlyConfigured
SESSION_KEY = '_auth_user_id'
BACKEND_SESSION_KEY = '_auth_user_backend'
LOGIN_URL = '/accounts/login/'
REDIRECT_FIELD_NAME = 'next'
def load_backend(path):
@ -49,6 +49,8 @@ def login(request, user):
if user is None:
user = request.user
# TODO: It would be nice to support different login methods, like signed cookies.
user.last_login = datetime.datetime.now()
user.save()
request.session[SESSION_KEY] = user.id
request.session[BACKEND_SESSION_KEY] = user.backend

View File

@ -1,13 +1,16 @@
from django.contrib.auth import LOGIN_URL, REDIRECT_FIELD_NAME
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.http import HttpResponseRedirect
from urllib import quote
def user_passes_test(test_func, login_url=LOGIN_URL):
def user_passes_test(test_func, login_url=None):
"""
Decorator for views that checks that the user passes the given test,
redirecting to the log-in page if necessary. The test should be a callable
that takes the user object and returns True if the user passes.
"""
if not login_url:
from django.conf import settings
login_url = settings.LOGIN_URL
def _dec(view_func):
def _checklogin(request, *args, **kwargs):
if test_func(request.user):
@ -27,7 +30,7 @@ login_required.__doc__ = (
"""
)
def permission_required(perm, login_url=LOGIN_URL):
def permission_required(perm, login_url=None):
"""
Decorator for views that checks whether a user has a particular permission
enabled, redirecting to the log-in page if necessary.

View File

@ -17,6 +17,12 @@ def check_password(raw_password, enc_password):
elif algo == 'sha1':
import sha
return hsh == sha.new(salt+raw_password).hexdigest()
elif algo == 'crypt':
try:
import crypt
except ImportError:
raise ValueError, "Crypt password algorithm not supported in this environment."
return hsh == crypt.crypt(raw_password, salt)
raise ValueError, "Got unknown password algorithm type in password."
class SiteProfileNotAvailable(Exception):
@ -95,8 +101,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_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."))
last_login = models.DateTimeField(_('last login'), default=models.LazyDate())
date_joined = models.DateTimeField(_('date joined'), default=models.LazyDate())
last_login = models.DateTimeField(_('last login'), default=datetime.datetime.now)
date_joined = models.DateTimeField(_('date joined'), default=datetime.datetime.now)
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."))
user_permissions = models.ManyToManyField(Permission, verbose_name=_('user permissions'), blank=True)
@ -258,7 +264,7 @@ class AnonymousUser(object):
pass
def __str__(self):
return 'AnonymousUser'
return _('AnonymousUser')
def __eq__(self, other):
return isinstance(other, self.__class__)

View File

@ -6,7 +6,7 @@ from django.template import RequestContext
from django.contrib.sites.models import Site
from django.http import HttpResponseRedirect
from django.contrib.auth.decorators import login_required
from django.contrib.auth import LOGIN_URL, REDIRECT_FIELD_NAME
from django.contrib.auth import REDIRECT_FIELD_NAME
def login(request, template_name='registration/login.html'):
"Displays the login form and handles the login action."
@ -17,7 +17,8 @@ def login(request, template_name='registration/login.html'):
if not errors:
# Light security check -- make sure redirect_to isn't garbage.
if not redirect_to or '://' in redirect_to or ' ' in redirect_to:
redirect_to = '/accounts/profile/'
from django.conf import settings
redirect_to = settings.LOGIN_REDIRECT_URL
from django.contrib.auth import login
login(request, manipulator.get_user())
request.session.delete_test_cookie()
@ -41,12 +42,18 @@ def logout(request, next_page=None, template_name='registration/logged_out.html'
# Redirect to this page until the session has been cleared.
return HttpResponseRedirect(next_page or request.path)
def logout_then_login(request, login_url=LOGIN_URL):
def logout_then_login(request, login_url=None):
"Logs out the user if he is logged in. Then redirects to the log-in page."
if not login_url:
from django.conf import settings
login_url = settings.LOGIN_URL
return logout(request, login_url)
def redirect_to_login(next, login_url=LOGIN_URL):
def redirect_to_login(next, login_url=None):
"Redirects the user to the login page, passing the given 'next' page"
if not login_url:
from django.conf import settings
login_url = settings.LOGIN_URL
return HttpResponseRedirect('%s?%s=%s' % (login_url, REDIRECT_FIELD_NAME, next))
def password_reset(request, is_admin_site=False, template_name='registration/password_reset_form.html',

View File

@ -3,7 +3,7 @@
<form {% if photos_optional or photos_required %}enctype="multipart/form-data" {% endif %}action="/comments/post/" method="post">
{% if user.is_authenticated %}
<p>{% trans "Username:" %} <strong>{{ user.username }}</strong> (<a href="/accounts/logout/">{% trans "Log out" %}</a>)</p>
<p>{% trans "Username:" %} <strong>{{ user.username }}</strong> (<a href="{{ logout_url }}">{% trans "Log out" %}</a>)</p>
{% else %}
<p><label for="id_username">{% trans "Username:" %}</label> <input type="text" name="username" id="id_username" /><br />{% trans "Password:" %} <input type="password" name="password" id="id_password" /> (<a href="/accounts/password_reset/">{% trans "Forgotten your password?" %}</a>)</p>
{% endif %}

View File

@ -25,6 +25,7 @@ class CommentFormNode(template.Node):
self.is_public = is_public
def render(self, context):
from django.conf import settings
from django.utils.text import normalize_newlines
import base64
context.push()
@ -64,6 +65,7 @@ class CommentFormNode(template.Node):
if self.rating_options:
context['rating_range'], context['rating_choices'] = Comment.objects.get_rating_options(self.rating_options)
context['hash'] = Comment.objects.get_security_hash(context['options'], context['photo_options'], context['rating_options'], context['target'])
context['logout_url'] = settings.LOGOUT_URL
default_form = loader.get_template(COMMENT_FORM)
output = default_form.render(context)
context.pop()
@ -114,7 +116,7 @@ class CommentListNode(template.Node):
comment_list = get_list_function(**kwargs).order_by(self.ordering + 'submit_date').select_related()
if not self.free:
if context.has_key('user') and context['user'].is_authenticated():
if 'user' in context and context['user'].is_authenticated():
user_id = context['user'].id
context['user_can_moderate_comments'] = Comment.objects.user_is_moderator(context['user'])
else:

View File

@ -217,10 +217,10 @@ def post_comment(request):
errors = manipulator.get_validation_errors(new_data)
# If user gave correct username/password and wasn't already logged in, log them in
# so they don't have to enter a username/password again.
if manipulator.get_user() and not manipulator.get_user().is_authenticated() and new_data.has_key('password') and manipulator.get_user().check_password(new_data['password']):
if manipulator.get_user() and not manipulator.get_user().is_authenticated() and 'password' in new_data and manipulator.get_user().check_password(new_data['password']):
from django.contrib.auth import login
login(request, manipulator.get_user())
if errors or request.POST.has_key('preview'):
if errors or 'preview' in request.POST:
class CommentFormWrapper(oldforms.FormWrapper):
def __init__(self, manipulator, new_data, errors, rating_choices):
oldforms.FormWrapper.__init__(self, manipulator, new_data, errors)
@ -244,7 +244,7 @@ def post_comment(request):
'rating_range': rating_range,
'rating_choices': rating_choices,
}, context_instance=RequestContext(request))
elif request.POST.has_key('post'):
elif 'post' in request.POST:
# If the IP is banned, mail the admins, do NOT save the comment, and
# serve up the "Thanks for posting" page as if the comment WAS posted.
if request.META['REMOTE_ADDR'] in settings.BANNED_IPS:
@ -298,7 +298,7 @@ def post_free_comment(request):
new_data['is_public'] = IS_PUBLIC in option_list
manipulator = PublicFreeCommentManipulator()
errors = manipulator.get_validation_errors(new_data)
if errors or request.POST.has_key('preview'):
if errors or 'preview' in request.POST:
comment = errors and '' or manipulator.get_comment(new_data)
return render_to_response('comments/free_preview.html', {
'comment': comment,
@ -307,7 +307,7 @@ def post_free_comment(request):
'target': target,
'hash': security_hash,
}, context_instance=RequestContext(request))
elif request.POST.has_key('post'):
elif 'post' in request.POST:
# If the IP is banned, mail the admins, do NOT save the comment, and
# serve up the "Thanks for posting" page as if the comment WAS posted.
if request.META['REMOTE_ADDR'] in settings.BANNED_IPS:
@ -330,7 +330,7 @@ def comment_was_posted(request):
The object the comment was posted on
"""
obj = None
if request.GET.has_key('c'):
if 'c' in request.GET:
content_type_id, object_id = request.GET['c'].split(':')
try:
content_type = ContentType.objects.get(pk=content_type_id)

View File

@ -16,18 +16,18 @@ class GenericForeignKey(object):
Provides a generic relation to any object through content-type/object-id
fields.
"""
def __init__(self, ct_field="content_type", fk_field="object_id"):
self.ct_field = ct_field
self.fk_field = fk_field
def contribute_to_class(self, cls, name):
# Make sure the fields exist (these raise FieldDoesNotExist,
# Make sure the fields exist (these raise FieldDoesNotExist,
# which is a fine error to raise here)
self.name = name
self.model = cls
self.cache_attr = "_%s_cache" % name
# For some reason I don't totally understand, using weakrefs here doesn't work.
dispatcher.connect(self.instance_pre_init, signal=signals.pre_init, sender=cls, weak=False)
@ -35,18 +35,18 @@ class GenericForeignKey(object):
setattr(cls, name, self)
def instance_pre_init(self, signal, sender, args, kwargs):
# Handle initalizing an object with the generic FK instaed of
# content-type/object-id fields.
if kwargs.has_key(self.name):
# Handle initalizing an object with the generic FK instaed of
# content-type/object-id fields.
if self.name in kwargs:
value = kwargs.pop(self.name)
kwargs[self.ct_field] = self.get_content_type(value)
kwargs[self.fk_field] = value._get_pk_val()
def get_content_type(self, obj):
# Convenience function using get_model avoids a circular import when using this model
ContentType = get_model("contenttypes", "contenttype")
return ContentType.objects.get_for_model(obj)
def __get__(self, instance, instance_type=None):
if instance is None:
raise AttributeError, "%s must be accessed via instance" % self.name
@ -77,21 +77,21 @@ class GenericForeignKey(object):
setattr(instance, self.ct_field, ct)
setattr(instance, self.fk_field, fk)
setattr(instance, self.cache_attr, value)
class GenericRelation(RelatedField, Field):
"""Provides an accessor to generic related objects (i.e. comments)"""
def __init__(self, to, **kwargs):
kwargs['verbose_name'] = kwargs.get('verbose_name', None)
kwargs['rel'] = GenericRel(to,
kwargs['rel'] = GenericRel(to,
related_name=kwargs.pop('related_name', None),
limit_choices_to=kwargs.pop('limit_choices_to', None),
symmetrical=kwargs.pop('symmetrical', True))
# Override content-type/object-id field names on the related class
self.object_id_field_name = kwargs.pop("object_id_field", "object_id")
self.content_type_field_name = kwargs.pop("content_type_field", "content_type")
self.content_type_field_name = kwargs.pop("content_type_field", "content_type")
kwargs['blank'] = True
kwargs['editable'] = False
kwargs['serialize'] = False
@ -116,7 +116,7 @@ class GenericRelation(RelatedField, Field):
def m2m_column_name(self):
return self.object_id_field_name
def m2m_reverse_name(self):
return self.object_id_field_name
@ -131,13 +131,13 @@ class GenericRelation(RelatedField, Field):
def contribute_to_related_class(self, cls, related):
pass
def set_attributes_from_rel(self):
pass
def get_internal_type(self):
return "ManyToManyField"
class ReverseGenericRelatedObjectsDescriptor(object):
"""
This class provides the functionality that makes the related-object
@ -191,12 +191,12 @@ def create_generic_related_manager(superclass):
Factory function for a manager that subclasses 'superclass' (which is a
Manager) and adds behavior for generic related objects.
"""
class GenericRelatedObjectManager(superclass):
def __init__(self, model=None, core_filters=None, instance=None, symmetrical=None,
join_table=None, source_col_name=None, target_col_name=None, content_type=None,
content_type_field_name=None, object_id_field_name=None):
super(GenericRelatedObjectManager, self).__init__()
self.core_filters = core_filters or {}
self.model = model
@ -210,10 +210,10 @@ def create_generic_related_manager(superclass):
self.content_type_field_name = content_type_field_name
self.object_id_field_name = object_id_field_name
self.pk_val = self.instance._get_pk_val()
def get_query_set(self):
query = {
'%s__pk' % self.content_type_field_name : self.content_type.id,
'%s__pk' % self.content_type_field_name : self.content_type.id,
'%s__exact' % self.object_id_field_name : self.pk_val,
}
return superclass.get_query_set(self).filter(**query)
@ -250,7 +250,11 @@ class GenericRel(ManyToManyRel):
self.to = to
self.num_in_admin = 0
self.related_name = related_name
self.filter_interface = None
self.limit_choices_to = limit_choices_to or {}
self.edit_inline = False
self.raw_id_admin = False
self.symmetrical = symmetrical
self.multiple = True
assert not (self.raw_id_admin and self.filter_interface), \
"Generic relations may not use both raw_id_admin and filter_interface"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,11 +1,9 @@
# -*- coding: utf-8 -*-
"""
A brazilian mapping of state misspellings/abbreviations to normalized
abbreviations, and an alphabetical list of states for use as `choices
in a formfield.
An alphabetical list of Brazilian states for use as `choices` in a formfield.
This exists in this standalone file so that it's only imported into
memory when explicitly needed.
This exists in this standalone file so that it's only imported into memory
when explicitly needed.
"""
STATE_CHOICES = (

View File

@ -4,7 +4,7 @@ BR-specific Form helpers
"""
from django.newforms import ValidationError
from django.newforms.fields import Field, RegexField, Select, EMPTY_VALUES
from django.newforms.fields import Field, RegexField, CharField, Select, EMPTY_VALUES
from django.utils.encoding import smart_unicode
from django.utils.translation import gettext
import re
@ -15,7 +15,7 @@ class BRZipCodeField(RegexField):
def __init__(self, *args, **kwargs):
super(BRZipCodeField, self).__init__(r'^\d{5}-\d{3}$',
max_length=None, min_length=None,
error_message=gettext(u'Enter a zip code in the format XXXXX-XXX.'),
error_message=gettext('Enter a zip code in the format XXXXX-XXX.'),
*args, **kwargs)
class BRPhoneNumberField(Field):
@ -31,9 +31,89 @@ class BRPhoneNumberField(Field):
class BRStateSelect(Select):
"""
A Select widget that uses a list of brazilian states/territories
A Select widget that uses a list of Brazilian states/territories
as its choices.
"""
def __init__(self, attrs=None):
from br_states import STATE_CHOICES # relative import
super(BRStateSelect, self).__init__(attrs, choices=STATE_CHOICES)
def DV_maker(v):
if v >= 2:
return 11 - v
return 0
class BRCPFField(CharField):
"""
This field validate a CPF number or a CPF string. A CPF number is
compounded by XXX.XXX.XXX-VD. The two last digits are check digits.
More information:
http://en.wikipedia.org/wiki/Cadastro_de_Pessoas_F%C3%ADsicas
"""
def __init__(self, *args, **kwargs):
super(BRCPFField, self).__init__(max_length=14, min_length=11, *args, **kwargs)
def clean(self, value):
"""
Value can be either a string in the format XXX.XXX.XXX-XX or an
11-digit number.
"""
value = super(BRCPFField, self).clean(value)
if value in EMPTY_VALUES:
return u''
orig_value = value[:]
if not value.isdigit():
value = re.sub("[-\.]", "", value)
try:
int(value)
except ValueError:
raise ValidationError(gettext("This field requires only numbers."))
if len(value) != 11:
raise ValidationError(gettext("This field requires at most 11 digits or 14 characters."))
orig_dv = value[-2:]
new_1dv = sum([i * int(value[idx]) for idx, i in enumerate(range(10, 1, -1))])
new_1dv = DV_maker(new_1dv % 11)
value = value[:-2] + str(new_1dv) + value[-1]
new_2dv = sum([i * int(value[idx]) for idx, i in enumerate(range(11, 1, -1))])
new_2dv = DV_maker(new_2dv % 11)
value = value[:-1] + str(new_2dv)
if value[-2:] != orig_dv:
raise ValidationError(gettext("Invalid CPF number."))
return orig_value
class BRCNPJField(Field):
def clean(self, value):
"""
Value can be either a string in the format XX.XXX.XXX/XXXX-XX or a
group of 14 characters.
"""
value = super(BRCNPJField, self).clean(value)
if value in EMPTY_VALUES:
return u''
orig_value = value[:]
if not value.isdigit():
value = re.sub("[-/\.]", "", value)
try:
int(value)
except ValueError:
raise ValidationError("This field requires only numbers.")
if len(value) != 14:
raise ValidationError(
gettext("This field requires at least 14 digits"))
orig_dv = value[-2:]
new_1dv = sum([i * int(value[idx]) for idx, i in enumerate(range(5, 1, -1) + range(9, 1, -1))])
new_1dv = DV_maker(new_1dv % 11)
value = value[:-2] + str(new_1dv) + value[-1]
new_2dv = sum([i * int(value[idx]) for idx, i in enumerate(range(6, 1, -1) + range(9, 1, -1))])
new_2dv = DV_maker(new_2dv % 11)
value = value[:-1] + str(new_2dv)
if value[-2:] != orig_dv:
raise ValidationError(gettext("Invalid CNPJ number."))
return orig_value

View File

@ -0,0 +1,31 @@
# -*- coding: utf-8 -*
from django.utils.translation import gettext_lazy as _
STATE_CHOICES = (
('AG', _('Aargau')),
('AI', _('Appenzell Innerrhoden')),
('AR', _('Appenzell Ausserrhoden')),
('BS', _('Basel-Stadt')),
('BL', _('Basel-Land')),
('BE', _('Berne')),
('FR', _('Fribourg')),
('GE', _('Geneva')),
('GL', _('Glarus')),
('GR', _('Graubuenden')),
('JU', _('Jura')),
('LU', _('Lucerne')),
('NE', _('Neuchatel')),
('NW', _('Nidwalden')),
('OW', _('Obwalden')),
('SH', _('Schaffhausen')),
('SZ', _('Schwyz')),
('SO', _('Solothurn')),
('SG', _('St. Gallen')),
('TG', _('Thurgau')),
('TI', _('Ticino')),
('UR', _('Uri')),
('VS', _('Valais')),
('VD', _('Vaud')),
('ZG', _('Zug')),
('ZH', _('Zurich'))
)

View File

@ -0,0 +1,109 @@
"""
Swiss-specific Form helpers
"""
from django.newforms import ValidationError
from django.newforms.fields import Field, RegexField, Select, EMPTY_VALUES
from django.utils.encoding import smart_unicode
from django.utils.translation import gettext
import re
id_re = re.compile(r"^(?P<idnumber>\w{8})(?P<pos9>(\d{1}|<))(?P<checksum>\d{1})$")
phone_digits_re = re.compile(r'^0([1-9]{1})\d{8}$')
class CHZipCodeField(RegexField):
def __init__(self, *args, **kwargs):
super(CHZipCodeField, self).__init__(r'^\d{4}$',
max_length=None, min_length=None,
error_message=gettext('Enter a zip code in the format XXXX.'),
*args, **kwargs)
class CHPhoneNumberField(Field):
"""
Validate local Swiss phone number (not international ones)
The correct format is '0XX XXX XX XX'.
'0XX.XXX.XX.XX' and '0XXXXXXXXX' validate but are corrected to
'0XX XXX XX XX'.
"""
def clean(self, value):
super(CHPhoneNumberField, self).clean(value)
if value in EMPTY_VALUES:
return u''
value = re.sub('(\.|\s|/|-)', '', smart_unicode(value))
m = phone_digits_re.search(value)
if m:
return u'%s %s %s %s' % (value[0:3], value[3:6], value[6:8], value[8:10])
raise ValidationError('Phone numbers must be in 0XX XXX XX XX format.')
class CHStateSelect(Select):
"""
A Select widget that uses a list of CH states as its choices.
"""
def __init__(self, attrs=None):
from ch_states import STATE_CHOICES # relative import
super(CHStateSelect, self).__init__(attrs, choices=STATE_CHOICES)
class CHIdentityCardNumberField(Field):
"""
A Swiss identity card number.
Checks the following rules to determine whether the number is valid:
* Conforms to the X1234567<0 or 1234567890 format.
* Included checksums match calculated checksums
Algorithm is documented at http://adi.kousz.ch/artikel/IDCHE.htm
"""
def has_valid_checksum(self, number):
given_number, given_checksum = number[:-1], number[-1]
new_number = given_number
calculated_checksum = 0
fragment = ""
parameter = 7
first = str(number[:1])
if first.isalpha():
num = ord(first.upper()) - 65
if num < 0 or num > 8:
return False
new_number = str(num) + new_number[1:]
new_number = new_number[:8] + '0'
if not new_number.isdigit():
return False
for i in range(len(new_number)):
fragment = int(new_number[i])*parameter
calculated_checksum += fragment
if parameter == 1:
parameter = 7
elif parameter == 3:
parameter = 1
elif parameter ==7:
parameter = 3
return str(calculated_checksum)[-1] == given_checksum
def clean(self, value):
super(CHIdentityCardNumberField, self).clean(value)
error_msg = gettext('Enter a valid Swiss identity or passport card number in X1234567<0 or 1234567890 format.')
if value in EMPTY_VALUES:
return u''
match = re.match(id_re, value)
if not match:
raise ValidationError(error_msg)
idnumber, pos9, checksum = match.groupdict()['idnumber'], match.groupdict()['pos9'], match.groupdict()['checksum']
if idnumber == '00000000' or \
idnumber == 'A0000000':
raise ValidationError(error_msg)
all_digits = "%s%s%s" % (idnumber, pos9, checksum)
if not self.has_valid_checksum(all_digits):
raise ValidationError(error_msg)
return u'%s%s%s' % (idnumber, pos9, checksum)

View File

@ -0,0 +1,78 @@
"""
Chile specific form helpers.
"""
from django.newforms import ValidationError
from django.newforms.fields import RegexField, EMPTY_VALUES
from django.utils.translation import gettext
class CLRutField(RegexField):
"""
Chilean "Rol Unico Tributario" (RUT) field. This is the Chilean national
identification number.
Samples for testing are available from
https://palena.sii.cl/cvc/dte/ee_empresas_emisoras.html
"""
def __init__(self, *args, **kwargs):
if 'strict' in kwargs:
del kwargs['strict']
super(CLRutField, self).__init__(r'^(\d{1,2}\.)?\d{3}\.\d{3}-[\dkK]$',
error_message=gettext('Enter valid a Chilean RUT. The format is XX.XXX.XXX-X.'),
*args, **kwargs)
else:
# In non-strict mode, accept RUTs that validate but do not exist in
# the real world.
super(CLRutField, self).__init__(r'^[\d\.]{1,11}-?[\dkK]$', error_message=gettext(u'Enter valid a Chilean RUT'), *args, **kwargs)
def clean(self, value):
"""
Check and clean the Chilean RUT.
"""
super(CLRutField, self).clean(value)
if value in EMPTY_VALUES:
return u''
rut, verificador = self._canonify(value)
if self._algorithm(rut) == verificador:
return self._format(rut, verificador)
else:
raise ValidationError(u'The Chilean RUT is not valid.')
def _algorithm(self, rut):
"""
Takes RUT in pure canonical form, calculates the verifier digit.
"""
suma = 0
multi = 2
for r in rut[::-1]:
suma += int(r) * multi
multi += 1
if multi == 8:
multi = 2
return '0123456789K0'[11 - suma % 11]
def _canonify(self, rut):
"""
Turns the RUT into one normalized format. Returns a (rut, verifier)
tuple.
"""
rut = str(rut).replace(' ', '').replace('.', '').replace('-', '')
return rut[:-1], rut[-1]
def _format(self, code, verifier=None):
"""
Formats the RUT from canonical form to the common string representation.
If verifier=None, then the last digit in 'code' is the verifier.
"""
if verifier is None:
verifier = code[-1]
code = code[:-1]
while len(code) > 3 and '.' not in code[:3]:
pos = code.find('.')
if pos == -1:
new_dot = -3
else:
new_dot = pos - 3
code = code[:new_dot] + '.' + code[new_dot:]
return '%s-%s' % (code, verifier)

View File

@ -26,8 +26,8 @@ class FISocialSecurityNumber(Field):
def clean(self, value):
super(FISocialSecurityNumber, self).clean(value)
if value in EMPTY_VALUES:
return u''
return u''
checkmarks = "0123456789ABCDEFHJKLMNPRSTUVWXY"
result = re.match(r"""^
(?P<date>([0-2]\d|3[01])
@ -35,13 +35,11 @@ class FISocialSecurityNumber(Field):
(\d{2}))
[A+-]
(?P<serial>(\d{3}))
(?P<chechsum>[%s])$""" % checkmarks, value, re.VERBOSE | re.IGNORECASE)
(?P<checksum>[%s])$""" % checkmarks, value, re.VERBOSE | re.IGNORECASE)
if not result:
raise ValidationError(gettext(u'Enter a valid Finnish social security number.'))
checksum = int(result.groupdict()['date'] + result.groupdict()['serial'])
if checkmarks[checksum % len(checkmarks)] == result.groupdict()['chechsum'].upper():
gd = result.groupdict()
checksum = int(gd['date'] + gd['serial'])
if checkmarks[checksum % len(checkmarks)] == gd['checksum'].upper():
return u'%s' % value.upper()
raise ValidationError(gettext(u'Enter a valid Finnish social security number.'))

View File

@ -0,0 +1,77 @@
"""
Iceland specific form helpers.
"""
from django.newforms import ValidationError
from django.newforms.fields import RegexField, EMPTY_VALUES
from django.newforms.widgets import Select
from django.utils.translation import gettext
class ISIdNumberField(RegexField):
"""
Icelandic identification number (kennitala). This is a number every citizen
of Iceland has.
"""
def __init__(self, *args, **kwargs):
error_msg = gettext(u'Enter a valid Icelandic identification number. The format is XXXXXX-XXXX.')
kwargs['min_length'],kwargs['max_length'] = 10,11
super(ISIdNumberField, self).__init__(r'^\d{6}(-| )?\d{4}$', error_message=error_msg, *args, **kwargs)
def clean(self, value):
value = super(ISIdNumberField, self).clean(value)
if value in EMPTY_VALUES:
return u''
value = self._canonify(value)
if self._validate(value):
return self._format(value)
else:
raise ValidationError(gettext(u'The Icelandic identification number is not valid.'))
def _canonify(self, value):
"""
Returns the value as only digits.
"""
return value.replace('-', '').replace(' ', '')
def _validate(self, value):
"""
Takes in the value in canonical form and checks the verifier digit. The
method is modulo 11.
"""
check = [3, 2, 7, 6, 5, 4, 3, 2, 1, 0]
return sum(int(value[i]) * check[i] for i in range(10)) % 11 == 0
def _format(self, value):
"""
Takes in the value in canonical form and returns it in the common
display format.
"""
return value[:6]+'-'+value[6:]
class ISPhoneNumberField(RegexField):
"""
Icelandic phone number. Seven digits with an optional hyphen or space after
the first three digits.
"""
def __init__(self, *args, **kwargs):
kwargs['min_length'], kwargs['max_length'] = 7,8
super(ISPhoneNumberField, self).__init__(r'^\d{3}(-| )?\d{4}$', *args, **kwargs)
def clean(self, value):
value = super(ISPhoneNumberField, self).clean(value)
if value in EMPTY_VALUES:
return u''
return value.replace('-', '').replace(' ', '')
class ISPostalCodeSelect(Select):
"""
A Select widget that uses a list of Icelandic postal codes as its choices.
"""
def __init__(self, attrs=None):
from is_postalcodes import IS_POSTALCODES
super(ISPostalCodeSelect, self).__init__(attrs, choices=IS_POSTALCODES)

View File

@ -0,0 +1,151 @@
# -*- coding: utf-8 -*-
IS_POSTALCODES = (
('101', u'101 Reykjavík'),
('103', u'103 Reykjavík'),
('104', u'104 Reykjavík'),
('105', u'105 Reykjavík'),
('107', u'107 Reykjavík'),
('108', u'108 Reykjavík'),
('109', u'109 Reykjavík'),
('110', u'110 Reykjavík'),
('111', u'111 Reykjavík'),
('112', u'112 Reykjavík'),
('113', u'113 Reykjavík'),
('116', u'116 Kjalarnes'),
('121', u'121 Reykjavík'),
('123', u'123 Reykjavík'),
('124', u'124 Reykjavík'),
('125', u'125 Reykjavík'),
('127', u'127 Reykjavík'),
('128', u'128 Reykjavík'),
('129', u'129 Reykjavík'),
('130', u'130 Reykjavík'),
('132', u'132 Reykjavík'),
('150', u'150 Reykjavík'),
('155', u'155 Reykjavík'),
('170', u'170 Seltjarnarnes'),
('172', u'172 Seltjarnarnes'),
('190', u'190 Vogar'),
('200', u'200 Kópavogur'),
('201', u'201 Kópavogur'),
('202', u'202 Kópavogur'),
('203', u'203 Kópavogur'),
('210', u'210 Garðabær'),
('212', u'212 Garðabær'),
('220', u'220 Hafnarfjörður'),
('221', u'221 Hafnarfjörður'),
('222', u'222 Hafnarfjörður'),
('225', u'225 Álftanes'),
('230', u'230 Reykjanesbær'),
('232', u'232 Reykjanesbær'),
('233', u'233 Reykjanesbær'),
('235', u'235 Keflavíkurflugvöllur'),
('240', u'240 Grindavík'),
('245', u'245 Sandgerði'),
('250', u'250 Garður'),
('260', u'260 Reykjanesbær'),
('270', u'270 Mosfellsbær'),
('300', u'300 Akranes'),
('301', u'301 Akranes'),
('302', u'302 Akranes'),
('310', u'310 Borgarnes'),
('311', u'311 Borgarnes'),
('320', u'320 Reykholt í Borgarfirði'),
('340', u'340 Stykkishólmur'),
('345', u'345 Flatey á Breiðafirði'),
('350', u'350 Grundarfjörður'),
('355', u'355 Ólafsvík'),
('356', u'356 Snæfellsbær'),
('360', u'360 Hellissandur'),
('370', u'370 Búðardalur'),
('371', u'371 Búðardalur'),
('380', u'380 Reykhólahreppur'),
('400', u'400 Ísafjörður'),
('401', u'401 Ísafjörður'),
('410', u'410 Hnífsdalur'),
('415', u'415 Bolungarvík'),
('420', u'420 Súðavík'),
('425', u'425 Flateyri'),
('430', u'430 Suðureyri'),
('450', u'450 Patreksfjörður'),
('451', u'451 Patreksfjörður'),
('460', u'460 Tálknafjörður'),
('465', u'465 Bíldudalur'),
('470', u'470 Þingeyri'),
('471', u'471 Þingeyri'),
('500', u'500 Staður'),
('510', u'510 Hólmavík'),
('512', u'512 Hólmavík'),
('520', u'520 Drangsnes'),
('522', u'522 Kjörvogur'),
('523', u'523 Bær'),
('524', u'524 Norðurfjörður'),
('530', u'530 Hvammstangi'),
('531', u'531 Hvammstangi'),
('540', u'540 Blönduós'),
('541', u'541 Blönduós'),
('545', u'545 Skagaströnd'),
('550', u'550 Sauðárkrókur'),
('551', u'551 Sauðárkrókur'),
('560', u'560 Varmahlíð'),
('565', u'565 Hofsós'),
('566', u'566 Hofsós'),
('570', u'570 Fljót'),
('580', u'580 Siglufjörður'),
('600', u'600 Akureyri'),
('601', u'601 Akureyri'),
('602', u'602 Akureyri'),
('603', u'603 Akureyri'),
('610', u'610 Grenivík'),
('611', u'611 Grímsey'),
('620', u'620 Dalvík'),
('621', u'621 Dalvík'),
('625', u'625 Ólafsfjörður'),
('630', u'630 Hrísey'),
('640', u'640 Húsavík'),
('641', u'641 Húsavík'),
('645', u'645 Fosshóll'),
('650', u'650 Laugar'),
('660', u'660 Mývatn'),
('670', u'670 Kópasker'),
('671', u'671 Kópasker'),
('675', u'675 Raufarhöfn'),
('680', u'680 Þórshöfn'),
('681', u'681 Þórshöfn'),
('685', u'685 Bakkafjörður'),
('690', u'690 Vopnafjörður'),
('700', u'700 Egilsstaðir'),
('701', u'701 Egilsstaðir'),
('710', u'710 Seyðisfjörður'),
('715', u'715 Mjóifjörður'),
('720', u'720 Borgarfjörður eystri'),
('730', u'730 Reyðarfjörður'),
('735', u'735 Eskifjörður'),
('740', u'740 Neskaupstaður'),
('750', u'750 Fáskrúðsfjörður'),
('755', u'755 Stöðvarfjörður'),
('760', u'760 Breiðdalsvík'),
('765', u'765 Djúpivogur'),
('780', u'780 Höfn í Hornafirði'),
('781', u'781 Höfn í Hornafirði'),
('785', u'785 Öræfi'),
('800', u'800 Selfoss'),
('801', u'801 Selfoss'),
('802', u'802 Selfoss'),
('810', u'810 Hveragerði'),
('815', u'815 Þorlákshöfn'),
('820', u'820 Eyrarbakki'),
('825', u'825 Stokkseyri'),
('840', u'840 Laugarvatn'),
('845', u'845 Flúðir'),
('850', u'850 Hella'),
('851', u'851 Hella'),
('860', u'860 Hvolsvöllur'),
('861', u'861 Hvolsvöllur'),
('870', u'870 Vík'),
('871', u'871 Vík'),
('880', u'880 Kirkjubæjarklaustur'),
('900', u'900 Vestmannaeyjar'),
('902', u'902 Vestmannaeyjar')
)

View File

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

View File

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

View File

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

View File

@ -16,7 +16,7 @@ def index(request, sitemaps):
def sitemap(request, sitemaps, section=None):
maps, urls = [], []
if section is not None:
if not sitemaps.has_key(section):
if section not in sitemaps:
raise Http404("No sitemap available for section: %r" % section)
maps.append(sitemaps[section])
else:

View File

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

View File

@ -1,66 +1,69 @@
"""
Utility functions for generating "lorem ipsum" Latin text.
"""
import random
COMMON_P = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'
WORDS = ('exercitationem', 'perferendis', 'perspiciatis', 'laborum', 'eveniet', 'sunt', 'iure', 'nam', 'nobis', 'eum', 'cum', 'officiis', 'excepturi', 'odio', 'consectetur', 'quasi', 'aut', 'quisquam', 'vel', 'eligendi', 'itaque', 'non', 'odit', 'tempore', 'quaerat', 'dignissimos', 'facilis', 'neque', 'nihil', 'expedita', 'vitae', 'vero', 'ipsum', 'nisi', 'animi', 'cumque', 'pariatur', 'velit', 'modi', 'natus', 'iusto', 'eaque', 'sequi', 'illo', 'sed', 'ex', 'et', 'voluptatibus', 'tempora', 'veritatis', 'ratione', 'assumenda', 'incidunt', 'nostrum', 'placeat', 'aliquid', 'fuga', 'provident', 'praesentium', 'rem', 'necessitatibus', 'suscipit', 'adipisci', 'quidem', 'possimus', 'voluptas', 'debitis', 'sint', 'accusantium', 'unde', 'sapiente', 'voluptate', 'qui', 'aspernatur', 'laudantium', 'soluta', 'amet', 'quo', 'aliquam', 'saepe', 'culpa', 'libero', 'ipsa', 'dicta', 'reiciendis', 'nesciunt', 'doloribus', 'autem', 'impedit', 'minima', 'maiores', 'repudiandae', 'ipsam', 'obcaecati', 'ullam', 'enim', 'totam', 'delectus', 'ducimus', 'quis', 'voluptates', 'dolores', 'molestiae', 'harum', 'dolorem', 'quia', 'voluptatem', 'molestias', 'magni', 'distinctio', 'omnis', 'illum', 'dolorum', 'voluptatum', 'ea', 'quas', 'quam', 'corporis', 'quae', 'blanditiis', 'atque', 'deserunt', 'laboriosam', 'earum', 'consequuntur', 'hic', 'cupiditate', 'quibusdam', 'accusamus', 'ut', 'rerum', 'error', 'minus', 'eius', 'ab', 'ad', 'nemo', 'fugit', 'officia', 'at', 'in', 'id', 'quos', 'reprehenderit', 'numquam', 'iste', 'fugiat', 'sit', 'inventore', 'beatae', 'repellendus', 'magnam', 'recusandae', 'quod', 'explicabo', 'doloremque', 'aperiam', 'consequatur', 'asperiores', 'commodi', 'optio', 'dolor', 'labore', 'temporibus', 'repellat', 'veniam', 'architecto', 'est', 'esse', 'mollitia', 'nulla', 'a', 'similique', 'eos', 'alias', 'dolore', 'tenetur', 'deleniti', 'porro', 'facere', 'maxime', 'corrupti')
COMMON_WORDS = ('lorem', 'ipsum', 'dolor', 'sit', 'amet', 'consectetur', 'adipisicing', 'elit', 'sed', 'do', 'eiusmod', 'tempor', 'incididunt', 'ut', 'labore', 'et', 'dolore', 'magna', 'aliqua')
def sentence():
"""
Returns a randomly generated sentence of lorem ipsum text.
The first word is capitalized, and the sentence ends in either a period or
question mark. Commas are added at random.
"""
# Determine the number of comma-separated sections and number of words in
# each section for this sentence.
sections = [' '.join(random.sample(WORDS, random.randint(3, 12))) for i in range(random.randint(1, 5))]
s = ', '.join(sections)
# Convert to sentence case and add end punctuation.
return '%s%s%s' % (s[0].upper(), s[1:], random.choice('?.'))
def paragraph():
"""
Returns a randomly generated paragraph of lorem ipsum text.
The paragraph consists of between 1 and 4 sentences, inclusive.
"""
return ' '.join([sentence() for i in range(random.randint(1, 4))])
def paragraphs(count, common=True):
"""
Returns a list of paragraphs as returned by paragraph().
If `common` is True, then the first paragraph will be the standard
'lorem ipsum' paragraph. Otherwise, the first paragraph will be random
Latin text. Either way, subsequent paragraphs will be random Latin text.
"""
paras = []
for i in range(count):
if common and i == 0:
paras.append(COMMON_P)
else:
paras.append(paragraph())
return paras
def words(count, common=True):
"""
Returns a string of `count` lorem ipsum words separated by a single space.
If `common` is True, then the first 19 words will be the standard
'lorem ipsum' words. Otherwise, all words will be selected randomly.
"""
if common:
word_list = list(COMMON_WORDS)
else:
word_list = []
c = len(word_list)
if count > c:
count = min(count - c, len(WORDS))
word_list += random.sample(WORDS, count - c)
else:
word_list = word_list[:count]
return ' '.join(word_list)
"""
Utility functions for generating "lorem ipsum" Latin text.
"""
import random
COMMON_P = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'
WORDS = ('exercitationem', 'perferendis', 'perspiciatis', 'laborum', 'eveniet', 'sunt', 'iure', 'nam', 'nobis', 'eum', 'cum', 'officiis', 'excepturi', 'odio', 'consectetur', 'quasi', 'aut', 'quisquam', 'vel', 'eligendi', 'itaque', 'non', 'odit', 'tempore', 'quaerat', 'dignissimos', 'facilis', 'neque', 'nihil', 'expedita', 'vitae', 'vero', 'ipsum', 'nisi', 'animi', 'cumque', 'pariatur', 'velit', 'modi', 'natus', 'iusto', 'eaque', 'sequi', 'illo', 'sed', 'ex', 'et', 'voluptatibus', 'tempora', 'veritatis', 'ratione', 'assumenda', 'incidunt', 'nostrum', 'placeat', 'aliquid', 'fuga', 'provident', 'praesentium', 'rem', 'necessitatibus', 'suscipit', 'adipisci', 'quidem', 'possimus', 'voluptas', 'debitis', 'sint', 'accusantium', 'unde', 'sapiente', 'voluptate', 'qui', 'aspernatur', 'laudantium', 'soluta', 'amet', 'quo', 'aliquam', 'saepe', 'culpa', 'libero', 'ipsa', 'dicta', 'reiciendis', 'nesciunt', 'doloribus', 'autem', 'impedit', 'minima', 'maiores', 'repudiandae', 'ipsam', 'obcaecati', 'ullam', 'enim', 'totam', 'delectus', 'ducimus', 'quis', 'voluptates', 'dolores', 'molestiae', 'harum', 'dolorem', 'quia', 'voluptatem', 'molestias', 'magni', 'distinctio', 'omnis', 'illum', 'dolorum', 'voluptatum', 'ea', 'quas', 'quam', 'corporis', 'quae', 'blanditiis', 'atque', 'deserunt', 'laboriosam', 'earum', 'consequuntur', 'hic', 'cupiditate', 'quibusdam', 'accusamus', 'ut', 'rerum', 'error', 'minus', 'eius', 'ab', 'ad', 'nemo', 'fugit', 'officia', 'at', 'in', 'id', 'quos', 'reprehenderit', 'numquam', 'iste', 'fugiat', 'sit', 'inventore', 'beatae', 'repellendus', 'magnam', 'recusandae', 'quod', 'explicabo', 'doloremque', 'aperiam', 'consequatur', 'asperiores', 'commodi', 'optio', 'dolor', 'labore', 'temporibus', 'repellat', 'veniam', 'architecto', 'est', 'esse', 'mollitia', 'nulla', 'a', 'similique', 'eos', 'alias', 'dolore', 'tenetur', 'deleniti', 'porro', 'facere', 'maxime', 'corrupti')
COMMON_WORDS = ('lorem', 'ipsum', 'dolor', 'sit', 'amet', 'consectetur', 'adipisicing', 'elit', 'sed', 'do', 'eiusmod', 'tempor', 'incididunt', 'ut', 'labore', 'et', 'dolore', 'magna', 'aliqua')
def sentence():
"""
Returns a randomly generated sentence of lorem ipsum text.
The first word is capitalized, and the sentence ends in either a period or
question mark. Commas are added at random.
"""
# Determine the number of comma-separated sections and number of words in
# each section for this sentence.
sections = [' '.join(random.sample(WORDS, random.randint(3, 12))) for i in range(random.randint(1, 5))]
s = ', '.join(sections)
# Convert to sentence case and add end punctuation.
return '%s%s%s' % (s[0].upper(), s[1:], random.choice('?.'))
def paragraph():
"""
Returns a randomly generated paragraph of lorem ipsum text.
The paragraph consists of between 1 and 4 sentences, inclusive.
"""
return ' '.join([sentence() for i in range(random.randint(1, 4))])
def paragraphs(count, common=True):
"""
Returns a list of paragraphs as returned by paragraph().
If `common` is True, then the first paragraph will be the standard
'lorem ipsum' paragraph. Otherwise, the first paragraph will be random
Latin text. Either way, subsequent paragraphs will be random Latin text.
"""
paras = []
for i in range(count):
if common and i == 0:
paras.append(COMMON_P)
else:
paras.append(paragraph())
return paras
def words(count, common=True):
"""
Returns a string of `count` lorem ipsum words separated by a single space.
If `common` is True, then the first 19 words will be the standard
'lorem ipsum' words. Otherwise, all words will be selected randomly.
"""
if common:
word_list = list(COMMON_WORDS)
else:
word_list = []
c = len(word_list)
if count > c:
count -= c
while count > 0:
c = min(count, len(WORDS))
count -= c
word_list += random.sample(WORDS, c)
else:
word_list = word_list[:count]
return ' '.join(word_list)

Some files were not shown because too many files have changed in this diff Show More