1
0
mirror of https://github.com/django/django.git synced 2025-07-04 09:49:12 +00:00

unicode: Merged from trunk up to [5121].

git-svn-id: http://code.djangoproject.com/svn/django/branches/unicode@5126 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Malcolm Tredinnick 2007-04-28 16:49:21 +00:00
parent 080cebaf69
commit 63d95548a7
62 changed files with 871 additions and 350 deletions

View File

@ -42,6 +42,7 @@ people who have submitted patches, reported bugs, added translations, helped
answer newbie questions, and generally made Django that much better: answer newbie questions, and generally made Django that much better:
adurdin@gmail.com adurdin@gmail.com
alang@bright-green.com
Daniel Alves Barbosa de Oliveira Vaz <danielvaz@gmail.com> Daniel Alves Barbosa de Oliveira Vaz <danielvaz@gmail.com>
Andreas Andreas
andy@jadedplanet.net andy@jadedplanet.net
@ -150,6 +151,7 @@ answer newbie questions, and generally made Django that much better:
Manuzhai Manuzhai
Petar Marić <http://www.petarmaric.com/> Petar Marić <http://www.petarmaric.com/>
Nuno Mariz <nmariz@gmail.com> Nuno Mariz <nmariz@gmail.com>
marijn@metronomo.cl
mark@junklight.com mark@junklight.com
Yasushi Masuda <whosaysni@gmail.com> Yasushi Masuda <whosaysni@gmail.com>
mattycakes@gmail.com mattycakes@gmail.com
@ -163,6 +165,7 @@ answer newbie questions, and generally made Django that much better:
Robin Munn <http://www.geekforgod.com/> Robin Munn <http://www.geekforgod.com/>
Robert Myers <myer0052@gmail.com> Robert Myers <myer0052@gmail.com>
Nebojša Dorđević Nebojša Dorđević
Gopal Narayanan <gopastro@gmail.com>
Fraser Nevett <mail@nevett.org> Fraser Nevett <mail@nevett.org>
Sam Newman <http://www.magpiebrain.com/> Sam Newman <http://www.magpiebrain.com/>
Neal Norwitz <nnorwitz@google.com> Neal Norwitz <nnorwitz@google.com>
@ -185,9 +188,11 @@ answer newbie questions, and generally made Django that much better:
Brian Ray <http://brianray.chipy.org/> Brian Ray <http://brianray.chipy.org/>
remco@diji.biz remco@diji.biz
rhettg@gmail.com rhettg@gmail.com
Henrique Romano <onaiort@gmail.com>
Armin Ronacher Armin Ronacher
Oliver Rutherfurd <http://rutherfurd.net/> Oliver Rutherfurd <http://rutherfurd.net/>
Ivan Sagalaev (Maniac) <http://www.softwaremaniacs.org/> Ivan Sagalaev (Maniac) <http://www.softwaremaniacs.org/>
Vinay Sajip <vinay_sajip@yahoo.co.uk>
David Schein David Schein
scott@staplefish.com scott@staplefish.com
serbaut@gmail.com serbaut@gmail.com
@ -211,6 +216,7 @@ answer newbie questions, and generally made Django that much better:
torne-django@wolfpuppy.org.uk torne-django@wolfpuppy.org.uk
Karen Tracey <graybark@bellsouth.net> Karen Tracey <graybark@bellsouth.net>
Makoto Tsuyuki <mtsuyuki@gmail.com> Makoto Tsuyuki <mtsuyuki@gmail.com>
tt@gurgle.no
Amit Upadhyay Amit Upadhyay
Geert Vanderkelen Geert Vanderkelen
viestards.lists@gmail.com viestards.lists@gmail.com

View File

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

View File

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

View File

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

View File

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

View File

@ -11,9 +11,10 @@ def patterns(prefix, *args):
pattern_list = [] pattern_list = []
for t in args: for t in args:
if isinstance(t, (list, tuple)): if isinstance(t, (list, tuple)):
pattern_list.append(url(prefix=prefix, *t)) t = url(prefix=prefix, *t)
else: elif isinstance(t, RegexURLPattern):
pattern_list.append(t) t.add_prefix(prefix)
pattern_list.append(t)
return pattern_list return pattern_list
def url(regex, view, kwargs=None, name=None, prefix=''): def url(regex, view, kwargs=None, name=None, prefix=''):

View File

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

View File

@ -17,7 +17,7 @@ def user_add_stage(request):
if not errors: if not errors:
new_user = manipulator.save(new_data) new_user = manipulator.save(new_data)
msg = _('The %(name)s "%(obj)s" was added successfully.') % {'name': 'user', 'obj': new_user} 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) request.user.message_set.create(message=msg)
return HttpResponseRedirect(request.path) return HttpResponseRedirect(request.path)
else: else:
@ -29,7 +29,7 @@ def user_add_stage(request):
return render_to_response('admin/auth/user/add_form.html', { return render_to_response('admin/auth/user/add_form.html', {
'title': _('Add user'), 'title': _('Add user'),
'form': form, 'form': form,
'is_popup': request.REQUEST.has_key('_popup'), 'is_popup': '_popup' in request.REQUEST,
'add': True, 'add': True,
'change': False, 'change': False,
'has_delete_permission': False, 'has_delete_permission': False,
@ -63,7 +63,7 @@ def user_change_password(request, id):
return render_to_response('admin/auth/user/change_password.html', { return render_to_response('admin/auth/user/change_password.html', {
'title': _('Change password: %s') % escape(user.username), 'title': _('Change password: %s') % escape(user.username),
'form': form, 'form': form,
'is_popup': request.REQUEST.has_key('_popup'), 'is_popup': '_popup' in request.REQUEST,
'add': True, 'add': True,
'change': False, 'change': False,
'has_delete_permission': 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=''): def _display_login_form(request, error_message=''):
request.session.set_test_cookie() 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. # User has failed login BUT has previously saved post data.
post_data = request.POST['post_data'] post_data = request.POST['post_data']
elif request.POST: elif request.POST:
@ -48,7 +48,7 @@ def staff_member_required(view_func):
def _checklogin(request, *args, **kwargs): def _checklogin(request, *args, **kwargs):
if request.user.is_authenticated() and request.user.is_staff: if request.user.is_authenticated() and request.user.is_staff:
# The user is valid. Continue to the admin page. # 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 # User must have re-authenticated through a different window
# or tab. # or tab.
request.POST = _decode_post_data(request.POST['post_data']) 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'." 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 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: if request.POST:
message = _("Please log in again, because your session has expired. Don't worry: Your submission has been saved.") message = _("Please log in again, because your session has expired. Don't worry: Your submission has been saved.")
else: else:
@ -90,9 +90,9 @@ def staff_member_required(view_func):
if user.is_active and user.is_staff: if user.is_active and user.is_staff:
login(request, user) login(request, user)
# TODO: set last_login with an event. # TODO: set last_login with an event.
if request.POST.has_key('post_data'): if 'post_data' in request.POST:
post_data = _decode_post_data(request.POST['post_data']) 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 # overwrite request.POST with the saved post_data, and continue
request.POST = post_data request.POST = post_data
request.user = user request.user = user

View File

@ -257,17 +257,17 @@ def add_stage(request, app_label, model_name, show_delete=False, form_url='', po
msg = _('The %(name)s "%(obj)s" was added successfully.') % {'name': opts.verbose_name, 'obj': new_object} msg = _('The %(name)s "%(obj)s" was added successfully.') % {'name': opts.verbose_name, 'obj': new_object}
# Here, we distinguish between different save types by checking for # Here, we distinguish between different save types by checking for
# the presence of keys in request.POST. # the presence of keys in request.POST.
if request.POST.has_key("_continue"): if "_continue" in request.POST:
request.user.message_set.create(message=msg + ' ' + _("You may edit it again below.")) request.user.message_set.create(message=msg + ' ' + _("You may edit it again below."))
if request.POST.has_key("_popup"): if "_popup" in request.POST:
post_url_continue += "?_popup=1" post_url_continue += "?_popup=1"
return HttpResponseRedirect(post_url_continue % pk_value) return HttpResponseRedirect(post_url_continue % pk_value)
if request.POST.has_key("_popup"): if "_popup" in request.POST:
if type(pk_value) is str: # Quote if string, so JavaScript doesn't think it's a variable. if type(pk_value) is str: # Quote if string, so JavaScript doesn't think it's a variable.
pk_value = '"%s"' % pk_value.replace('"', '\\"') pk_value = '"%s"' % pk_value.replace('"', '\\"')
return HttpResponse('<script type="text/javascript">opener.dismissAddAnotherPopup(window, %s, "%s");</script>' % \ return HttpResponse('<script type="text/javascript">opener.dismissAddAnotherPopup(window, %s, "%s");</script>' % \
(pk_value, str(new_object).replace('"', '\\"'))) (pk_value, str(new_object).replace('"', '\\"')))
elif request.POST.has_key("_addanother"): elif "_addanother" in request.POST:
request.user.message_set.create(message=msg + ' ' + (_("You may add another %s below.") % opts.verbose_name)) request.user.message_set.create(message=msg + ' ' + (_("You may add another %s below.") % opts.verbose_name))
return HttpResponseRedirect(request.path) return HttpResponseRedirect(request.path)
else: else:
@ -288,7 +288,7 @@ def add_stage(request, app_label, model_name, show_delete=False, form_url='', po
c = template.RequestContext(request, { c = template.RequestContext(request, {
'title': _('Add %s') % opts.verbose_name, 'title': _('Add %s') % opts.verbose_name,
'form': form, 'form': form,
'is_popup': request.REQUEST.has_key('_popup'), 'is_popup': '_popup' in request.REQUEST,
'show_delete': show_delete, 'show_delete': show_delete,
}) })
@ -308,7 +308,7 @@ def change_stage(request, app_label, model_name, object_id):
if not request.user.has_perm(app_label + '.' + opts.get_change_permission()): if not request.user.has_perm(app_label + '.' + opts.get_change_permission()):
raise PermissionDenied raise PermissionDenied
if request.POST and request.POST.has_key("_saveasnew"): if request.POST and "_saveasnew" in request.POST:
return add_stage(request, app_label, model_name, form_url='../../add/') return add_stage(request, app_label, model_name, form_url='../../add/')
try: try:
@ -343,16 +343,16 @@ def change_stage(request, app_label, model_name, object_id):
LogEntry.objects.log_action(request.user.id, ContentType.objects.get_for_model(model).id, pk_value, str(new_object), CHANGE, change_message) LogEntry.objects.log_action(request.user.id, ContentType.objects.get_for_model(model).id, pk_value, str(new_object), CHANGE, change_message)
msg = _('The %(name)s "%(obj)s" was changed successfully.') % {'name': opts.verbose_name, 'obj': new_object} msg = _('The %(name)s "%(obj)s" was changed successfully.') % {'name': opts.verbose_name, 'obj': new_object}
if request.POST.has_key("_continue"): if "_continue" in request.POST:
request.user.message_set.create(message=msg + ' ' + _("You may edit it again below.")) request.user.message_set.create(message=msg + ' ' + _("You may edit it again below."))
if request.REQUEST.has_key('_popup'): if '_popup' in request.REQUEST:
return HttpResponseRedirect(request.path + "?_popup=1") return HttpResponseRedirect(request.path + "?_popup=1")
else: else:
return HttpResponseRedirect(request.path) return HttpResponseRedirect(request.path)
elif request.POST.has_key("_saveasnew"): elif "_saveasnew" in request.POST:
request.user.message_set.create(message=_('The %(name)s "%(obj)s" was added successfully. You may edit it again below.') % {'name': opts.verbose_name, 'obj': new_object}) request.user.message_set.create(message=_('The %(name)s "%(obj)s" was added successfully. You may edit it again below.') % {'name': opts.verbose_name, 'obj': new_object})
return HttpResponseRedirect("../%s/" % pk_value) return HttpResponseRedirect("../%s/" % pk_value)
elif request.POST.has_key("_addanother"): elif "_addanother" in request.POST:
request.user.message_set.create(message=msg + ' ' + (_("You may add another %s below.") % opts.verbose_name)) request.user.message_set.create(message=msg + ' ' + (_("You may add another %s below.") % opts.verbose_name))
return HttpResponseRedirect("../add/") return HttpResponseRedirect("../add/")
else: else:
@ -392,7 +392,7 @@ def change_stage(request, app_label, model_name, object_id):
'form': form, 'form': form,
'object_id': object_id, 'object_id': object_id,
'original': manipulator.original_object, 'original': manipulator.original_object,
'is_popup': request.REQUEST.has_key('_popup'), 'is_popup': '_popup' in request.REQUEST,
}) })
return render_change_form(model, manipulator, c, change=True) return render_change_form(model, manipulator, c, change=True)
change_stage = staff_member_required(never_cache(change_stage)) change_stage = staff_member_required(never_cache(change_stage))
@ -558,12 +558,12 @@ class ChangeList(object):
self.page_num = int(request.GET.get(PAGE_VAR, 0)) self.page_num = int(request.GET.get(PAGE_VAR, 0))
except ValueError: except ValueError:
self.page_num = 0 self.page_num = 0
self.show_all = request.GET.has_key(ALL_VAR) self.show_all = ALL_VAR in request.GET
self.is_popup = request.GET.has_key(IS_POPUP_VAR) self.is_popup = IS_POPUP_VAR in request.GET
self.params = dict(request.GET.items()) self.params = dict(request.GET.items())
if self.params.has_key(PAGE_VAR): if PAGE_VAR in self.params:
del self.params[PAGE_VAR] del self.params[PAGE_VAR]
if self.params.has_key(ERROR_FLAG): if ERROR_FLAG in self.params:
del self.params[ERROR_FLAG] del self.params[ERROR_FLAG]
self.order_field, self.order_type = self.get_ordering() self.order_field, self.order_type = self.get_ordering()
@ -594,7 +594,7 @@ class ChangeList(object):
if k.startswith(r): if k.startswith(r):
del p[k] del p[k]
for k, v in new_params.items(): 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] del p[k]
elif v is not None: elif v is not None:
p[k] = v p[k] = v
@ -656,7 +656,7 @@ class ChangeList(object):
order_field, order_type = ordering[0][1:], 'desc' order_field, order_type = ordering[0][1:], 'desc'
else: else:
order_field, order_type = ordering[0], 'asc' order_field, order_type = ordering[0], 'asc'
if params.has_key(ORDER_VAR): if ORDER_VAR in params:
try: try:
field_name = lookup_opts.admin.list_display[int(params[ORDER_VAR])] field_name = lookup_opts.admin.list_display[int(params[ORDER_VAR])]
try: try:
@ -674,7 +674,7 @@ class ChangeList(object):
order_field = f.name order_field = f.name
except (IndexError, ValueError): except (IndexError, ValueError):
pass # Invalid ordering specified. Just use the default. 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] order_type = params[ORDER_TYPE_VAR]
return order_field, order_type return order_field, order_type
@ -682,7 +682,7 @@ class ChangeList(object):
qs = self.manager.get_query_set() qs = self.manager.get_query_set()
lookup_params = self.params.copy() # a dictionary of the query string 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): 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] del lookup_params[i]
# Apply lookup parameters from the query string. # Apply lookup parameters from the query string.

View File

@ -116,7 +116,7 @@ class CommentListNode(template.Node):
comment_list = get_list_function(**kwargs).order_by(self.ordering + 'submit_date').select_related() comment_list = get_list_function(**kwargs).order_by(self.ordering + 'submit_date').select_related()
if not self.free: 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 user_id = context['user'].id
context['user_can_moderate_comments'] = Comment.objects.user_is_moderator(context['user']) context['user_can_moderate_comments'] = Comment.objects.user_is_moderator(context['user'])
else: else:

View File

@ -217,10 +217,10 @@ def post_comment(request):
errors = manipulator.get_validation_errors(new_data) errors = manipulator.get_validation_errors(new_data)
# If user gave correct username/password and wasn't already logged in, log them in # 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. # 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 from django.contrib.auth import login
login(request, manipulator.get_user()) login(request, manipulator.get_user())
if errors or request.POST.has_key('preview'): if errors or 'preview' in request.POST:
class CommentFormWrapper(oldforms.FormWrapper): class CommentFormWrapper(oldforms.FormWrapper):
def __init__(self, manipulator, new_data, errors, rating_choices): def __init__(self, manipulator, new_data, errors, rating_choices):
oldforms.FormWrapper.__init__(self, manipulator, new_data, errors) oldforms.FormWrapper.__init__(self, manipulator, new_data, errors)
@ -244,7 +244,7 @@ def post_comment(request):
'rating_range': rating_range, 'rating_range': rating_range,
'rating_choices': rating_choices, 'rating_choices': rating_choices,
}, context_instance=RequestContext(request)) }, 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 # 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. # serve up the "Thanks for posting" page as if the comment WAS posted.
if request.META['REMOTE_ADDR'] in settings.BANNED_IPS: 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 new_data['is_public'] = IS_PUBLIC in option_list
manipulator = PublicFreeCommentManipulator() manipulator = PublicFreeCommentManipulator()
errors = manipulator.get_validation_errors(new_data) 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) comment = errors and '' or manipulator.get_comment(new_data)
return render_to_response('comments/free_preview.html', { return render_to_response('comments/free_preview.html', {
'comment': comment, 'comment': comment,
@ -307,7 +307,7 @@ def post_free_comment(request):
'target': target, 'target': target,
'hash': security_hash, 'hash': security_hash,
}, context_instance=RequestContext(request)) }, 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 # 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. # serve up the "Thanks for posting" page as if the comment WAS posted.
if request.META['REMOTE_ADDR'] in settings.BANNED_IPS: 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 The object the comment was posted on
""" """
obj = None obj = None
if request.GET.has_key('c'): if 'c' in request.GET:
content_type_id, object_id = request.GET['c'].split(':') content_type_id, object_id = request.GET['c'].split(':')
try: try:
content_type = ContentType.objects.get(pk=content_type_id) content_type = ContentType.objects.get(pk=content_type_id)

View File

@ -4,7 +4,7 @@ BR-specific Form helpers
""" """
from django.newforms import ValidationError from django.newforms import ValidationError
from django.newforms.fields import Field, RegexField, Select, EMPTY_VALUES from django.newforms.fields import Field, RegexField, CharField, Select, EMPTY_VALUES
from django.utils.encoding import smart_unicode from django.utils.encoding import smart_unicode
from django.utils.translation import gettext from django.utils.translation import gettext
import re import re
@ -15,7 +15,7 @@ class BRZipCodeField(RegexField):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(BRZipCodeField, self).__init__(r'^\d{5}-\d{3}$', super(BRZipCodeField, self).__init__(r'^\d{5}-\d{3}$',
max_length=None, min_length=None, 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) *args, **kwargs)
class BRPhoneNumberField(Field): class BRPhoneNumberField(Field):
@ -31,9 +31,89 @@ class BRPhoneNumberField(Field):
class BRStateSelect(Select): 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. as its choices.
""" """
def __init__(self, attrs=None): def __init__(self, attrs=None):
from br_states import STATE_CHOICES # relative import from br_states import STATE_CHOICES # relative import
super(BRStateSelect, self).__init__(attrs, choices=STATE_CHOICES) 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,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

@ -1,12 +1,12 @@
""" """
Iceland specific form helpers. Iceland specific form helpers.
""" """
from django.newforms import ValidationError from django.newforms import ValidationError
from django.newforms.fields import RegexField, EMPTY_VALUES from django.newforms.fields import RegexField, EMPTY_VALUES
from django.newforms.widgets import Select from django.newforms.widgets import Select
from django.utils.translation import gettext from django.utils.translation import gettext
class ISIdNumberField(RegexField): class ISIdNumberField(RegexField):
""" """
Icelandic identification number (kennitala). This is a number every citizen Icelandic identification number (kennitala). This is a number every citizen
@ -15,7 +15,6 @@ class ISIdNumberField(RegexField):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
error_msg = gettext(u'Enter a valid Icelandic identification number. The format is XXXXXX-XXXX.') error_msg = gettext(u'Enter a valid Icelandic identification number. The format is XXXXXX-XXXX.')
kwargs['min_length'],kwargs['max_length'] = 10,11 kwargs['min_length'],kwargs['max_length'] = 10,11
super(ISIdNumberField, self).__init__(r'^\d{6}(-| )?\d{4}$', error_message=error_msg, *args, **kwargs) super(ISIdNumberField, self).__init__(r'^\d{6}(-| )?\d{4}$', error_message=error_msg, *args, **kwargs)
def clean(self, value): def clean(self, value):
@ -30,7 +29,6 @@ class ISIdNumberField(RegexField):
else: else:
raise ValidationError(gettext(u'The Icelandic identification number is not valid.')) raise ValidationError(gettext(u'The Icelandic identification number is not valid.'))
def _canonify(self, value): def _canonify(self, value):
""" """
Returns the value as only digits. Returns the value as only digits.
@ -52,7 +50,6 @@ class ISIdNumberField(RegexField):
""" """
return value[:6]+'-'+value[6:] return value[:6]+'-'+value[6:]
class ISPhoneNumberField(RegexField): class ISPhoneNumberField(RegexField):
""" """
Icelandic phone number. Seven digits with an optional hyphen or space after Icelandic phone number. Seven digits with an optional hyphen or space after
@ -70,7 +67,6 @@ class ISPhoneNumberField(RegexField):
return value.replace('-', '').replace(' ', '') return value.replace('-', '').replace(' ', '')
class ISPostalCodeSelect(Select): class ISPostalCodeSelect(Select):
""" """
A Select widget that uses a list of Icelandic postal codes as its choices. A Select widget that uses a list of Icelandic postal codes as its choices.

View File

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

View File

@ -52,7 +52,7 @@ class CacheClass(BaseCache):
pass pass
def has_key(self, key): def has_key(self, key):
return self._cache.has_key(key) return key in self._cache
def _cull(self): def _cull(self):
if self._cull_frequency == 0: if self._cull_frequency == 0:

View File

@ -42,11 +42,11 @@ class ModPythonRequest(http.HttpRequest):
def is_secure(self): def is_secure(self):
# Note: modpython 3.2.10+ has req.is_https(), but we need to support previous versions # Note: modpython 3.2.10+ has req.is_https(), but we need to support previous versions
return self._req.subprocess_env.has_key('HTTPS') and self._req.subprocess_env['HTTPS'] == 'on' return 'HTTPS' in self._req.subprocess_env and self._req.subprocess_env['HTTPS'] == 'on'
def _load_post_and_files(self): def _load_post_and_files(self):
"Populates self._post and self._files" "Populates self._post and self._files"
if self._req.headers_in.has_key('content-type') and self._req.headers_in['content-type'].startswith('multipart'): if 'content-type' in self._req.headers_in and self._req.headers_in['content-type'].startswith('multipart'):
self._post, self._files = http.parse_file_upload(self._req.headers_in, self.raw_post_data) self._post, self._files = http.parse_file_upload(self._req.headers_in, self.raw_post_data)
else: else:
self._post, self._files = http.QueryDict(self.raw_post_data), datastructures.MultiValueDict() self._post, self._files = http.QueryDict(self.raw_post_data), datastructures.MultiValueDict()

View File

@ -103,7 +103,7 @@ class WSGIRequest(http.HttpRequest):
return '%s%s' % (self.path, self.environ.get('QUERY_STRING', '') and ('?' + self.environ.get('QUERY_STRING', '')) or '') return '%s%s' % (self.path, self.environ.get('QUERY_STRING', '') and ('?' + self.environ.get('QUERY_STRING', '')) or '')
def is_secure(self): def is_secure(self):
return self.environ.has_key('HTTPS') and self.environ['HTTPS'] == 'on' return 'HTTPS' in self.environ and self.environ['HTTPS'] == 'on'
def _load_post_and_files(self): def _load_post_and_files(self):
# Populates self._post and self._files # Populates self._post and self._files

View File

@ -168,6 +168,8 @@ def _get_sql_model_create(model, known_models=set()):
for f in opts.fields: for f in opts.fields:
if isinstance(f, (models.ForeignKey, models.OneToOneField)): if isinstance(f, (models.ForeignKey, models.OneToOneField)):
rel_field = f.rel.get_related_field() rel_field = f.rel.get_related_field()
while isinstance(rel_field, (models.ForeignKey, models.OneToOneField)):
rel_field = rel_field.rel.get_related_field()
data_type = get_rel_data_type(rel_field) data_type = get_rel_data_type(rel_field)
else: else:
rel_field = f rel_field = f
@ -314,7 +316,7 @@ def get_sql_delete(app):
# Drop the table now # Drop the table now
output.append('%s %s;' % (style.SQL_KEYWORD('DROP TABLE'), output.append('%s %s;' % (style.SQL_KEYWORD('DROP TABLE'),
style.SQL_TABLE(backend.quote_name(model._meta.db_table)))) style.SQL_TABLE(backend.quote_name(model._meta.db_table))))
if backend.supports_constraints and references_to_delete.has_key(model): if backend.supports_constraints and model in references_to_delete:
for rel_class, f in references_to_delete[model]: for rel_class, f in references_to_delete[model]:
table = rel_class._meta.db_table table = rel_class._meta.db_table
col = f.column col = f.column
@ -843,7 +845,7 @@ def inspectdb():
att_name += '_field' att_name += '_field'
comment_notes.append('Field renamed because it was a Python reserved word.') comment_notes.append('Field renamed because it was a Python reserved word.')
if relations.has_key(i): if i in relations:
rel_to = relations[i][1] == table_name and "'self'" or table2model(relations[i][1]) rel_to = relations[i][1] == table_name and "'self'" or table2model(relations[i][1])
field_type = 'ForeignKey(%s' % rel_to field_type = 'ForeignKey(%s' % rel_to
if att_name.endswith('_id'): if att_name.endswith('_id'):
@ -1318,6 +1320,8 @@ def load_data(fixture_labels, verbosity=1):
from django.conf import settings from django.conf import settings
import sys import sys
disable_termcolors()
# Keep a count of the installed objects and fixtures # Keep a count of the installed objects and fixtures
count = [0,0] count = [0,0]
models = set() models = set()
@ -1550,7 +1554,7 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None):
action = args[0] action = args[0]
except IndexError: except IndexError:
parser.print_usage_and_exit() parser.print_usage_and_exit()
if not action_mapping.has_key(action): if action not in action_mapping:
print_error("Your action, %r, was invalid." % action, argv[0]) print_error("Your action, %r, was invalid." % action, argv[0])
# Switch to English, because django-admin.py creates database content # Switch to English, because django-admin.py creates database content

View File

@ -208,15 +208,15 @@ def guess_scheme(environ):
else: else:
return 'http' return 'http'
_hoppish = { _hop_headers = {
'connection':1, 'keep-alive':1, 'proxy-authenticate':1, 'connection':1, 'keep-alive':1, 'proxy-authenticate':1,
'proxy-authorization':1, 'te':1, 'trailers':1, 'transfer-encoding':1, 'proxy-authorization':1, 'te':1, 'trailers':1, 'transfer-encoding':1,
'upgrade':1 'upgrade':1
}.has_key }
def is_hop_by_hop(header_name): def is_hop_by_hop(header_name):
"""Return true if 'header_name' is an HTTP/1.1 "Hop-by-Hop" header""" """Return true if 'header_name' is an HTTP/1.1 "Hop-by-Hop" header"""
return _hoppish(header_name.lower()) return header_name.lower() in _hop_headers
class ServerHandler(object): class ServerHandler(object):
"""Manage the invocation of a WSGI application""" """Manage the invocation of a WSGI application"""
@ -334,7 +334,7 @@ class ServerHandler(object):
Subclasses can extend this to add other defaults. Subclasses can extend this to add other defaults.
""" """
if not self.headers.has_key('Content-Length'): if 'Content-Length' not in self.headers:
self.set_content_length() self.set_content_length()
def start_response(self, status, headers,exc_info=None): def start_response(self, status, headers,exc_info=None):
@ -368,11 +368,11 @@ class ServerHandler(object):
if self.origin_server: if self.origin_server:
if self.client_is_modern(): if self.client_is_modern():
self._write('HTTP/%s %s\r\n' % (self.http_version,self.status)) self._write('HTTP/%s %s\r\n' % (self.http_version,self.status))
if not self.headers.has_key('Date'): if 'Date' not in self.headers:
self._write( self._write(
'Date: %s\r\n' % time.asctime(time.gmtime(time.time())) 'Date: %s\r\n' % time.asctime(time.gmtime(time.time()))
) )
if self.server_software and not self.headers.has_key('Server'): if self.server_software and 'Server' not in self.headers:
self._write('Server: %s\r\n' % self.server_software) self._write('Server: %s\r\n' % self.server_software)
else: else:
self._write('Status: %s\r\n' % self.status) self._write('Status: %s\r\n' % self.status)

View File

@ -102,6 +102,14 @@ class RegexURLPattern(object):
self.default_args = default_args or {} self.default_args = default_args or {}
self.name = name self.name = name
def add_prefix(self, prefix):
"""
Adds the prefix string to a string-based callback.
"""
if not prefix or not hasattr(self, '_callback_str'):
return
self._callback_str = prefix + '.' + self._callback_str
def resolve(self, path): def resolve(self, path):
match = self.regex.search(path) match = self.regex.search(path)
if match: if match:

View File

@ -284,7 +284,7 @@ class ValidateIfOtherFieldEquals(object):
self.always_test = True self.always_test = True
def __call__(self, field_data, all_data): def __call__(self, field_data, all_data):
if all_data.has_key(self.other_field) and all_data[self.other_field] == self.other_value: if self.other_field in all_data and all_data[self.other_field] == self.other_value:
for v in self.validator_list: for v in self.validator_list:
v(field_data, all_data) v(field_data, all_data)
@ -322,7 +322,7 @@ class RequiredIfOtherFieldEquals(object):
self.always_test = True self.always_test = True
def __call__(self, field_data, all_data): def __call__(self, field_data, all_data):
if all_data.has_key(self.other_field) and all_data[self.other_field] == self.other_value and not field_data: if self.other_field in all_data and all_data[self.other_field] == self.other_value and not field_data:
raise ValidationError(self.error_message) raise ValidationError(self.error_message)
class RequiredIfOtherFieldDoesNotEqual(object): class RequiredIfOtherFieldDoesNotEqual(object):
@ -335,7 +335,7 @@ class RequiredIfOtherFieldDoesNotEqual(object):
self.always_test = True self.always_test = True
def __call__(self, field_data, all_data): def __call__(self, field_data, all_data):
if all_data.has_key(self.other_field) and all_data[self.other_field] != self.other_value and not field_data: if self.other_field in all_data and all_data[self.other_field] != self.other_value and not field_data:
raise ValidationError(self.error_message) raise ValidationError(self.error_message)
class IsLessThanOtherField(object): class IsLessThanOtherField(object):

View File

@ -53,7 +53,7 @@ class MysqlDebugWrapper:
raise Database.Warning, "%s: %s" % (w, self.cursor.fetchall()) raise Database.Warning, "%s: %s" % (w, self.cursor.fetchall())
def __getattr__(self, attr): def __getattr__(self, attr):
if self.__dict__.has_key(attr): if attr in self.__dict__:
return self.__dict__[attr] return self.__dict__[attr]
else: else:
return getattr(self.cursor, attr) return getattr(self.cursor, attr)

View File

@ -48,7 +48,7 @@ class UnicodeCursorWrapper(object):
return self.cursor.executemany(sql, new_param_list) return self.cursor.executemany(sql, new_param_list)
def __getattr__(self, attr): def __getattr__(self, attr):
if self.__dict__.has_key(attr): if attr in self.__dict__:
return self.__dict__[attr] return self.__dict__[attr]
else: else:
return getattr(self.cursor, attr) return getattr(self.cursor, attr)

View File

@ -33,7 +33,7 @@ class CursorDebugWrapper(object):
}) })
def __getattr__(self, attr): def __getattr__(self, attr):
if self.__dict__.has_key(attr): if attr in self.__dict__:
return self.__dict__[attr] return self.__dict__[attr]
else: else:
return getattr(self.cursor, attr) return getattr(self.cursor, attr)

View File

@ -341,11 +341,13 @@ class Field(object):
return self._choices return self._choices
choices = property(_get_choices) choices = property(_get_choices)
def formfield(self, **kwargs): def formfield(self, form_class=forms.CharField, **kwargs):
"Returns a django.newforms.Field instance for this database Field." "Returns a django.newforms.Field instance for this database Field."
defaults = {'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text} defaults = {'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text}
if self.choices:
defaults['widget'] = forms.Select(choices=self.get_choices())
defaults.update(kwargs) defaults.update(kwargs)
return forms.CharField(**defaults) return form_class(**defaults)
def value_from_object(self, obj): def value_from_object(self, obj):
"Returns the value of this field in the given model instance." "Returns the value of this field in the given model instance."
@ -405,9 +407,9 @@ class BooleanField(Field):
return [oldforms.CheckboxField] return [oldforms.CheckboxField]
def formfield(self, **kwargs): def formfield(self, **kwargs):
defaults = {'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text} defaults = {'form_class': forms.BooleanField}
defaults.update(kwargs) defaults.update(kwargs)
return forms.BooleanField(**defaults) return super(BooleanField, self).formfield(**defaults)
class CharField(Field): class CharField(Field):
def get_manipulator_field_objs(self): def get_manipulator_field_objs(self):
@ -424,9 +426,9 @@ class CharField(Field):
return str(value) return str(value)
def formfield(self, **kwargs): def formfield(self, **kwargs):
defaults = {'max_length': self.maxlength, 'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text} defaults = {'max_length': self.maxlength}
defaults.update(kwargs) defaults.update(kwargs)
return forms.CharField(**defaults) return super(CharField, self).formfield(**defaults)
# TODO: Maybe move this into contrib, because it's specialized. # TODO: Maybe move this into contrib, because it's specialized.
class CommaSeparatedIntegerField(CharField): class CommaSeparatedIntegerField(CharField):
@ -502,9 +504,9 @@ class DateField(Field):
return {self.attname: (val is not None and val.strftime("%Y-%m-%d") or '')} return {self.attname: (val is not None and val.strftime("%Y-%m-%d") or '')}
def formfield(self, **kwargs): def formfield(self, **kwargs):
defaults = {'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text} defaults = {'form_class': forms.DateField}
defaults.update(kwargs) defaults.update(kwargs)
return forms.DateField(**defaults) return super(DateField, self).formfield(**defaults)
class DateTimeField(DateField): class DateTimeField(DateField):
def to_python(self, value): def to_python(self, value):
@ -567,9 +569,9 @@ class DateTimeField(DateField):
time_field: (val is not None and val.strftime("%H:%M:%S") or '')} time_field: (val is not None and val.strftime("%H:%M:%S") or '')}
def formfield(self, **kwargs): def formfield(self, **kwargs):
defaults = {'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text} defaults = {'form_class': forms.DateTimeField}
defaults.update(kwargs) defaults.update(kwargs)
return forms.DateTimeField(**defaults) return super(DateTimeField, self).formfield(**defaults)
class EmailField(CharField): class EmailField(CharField):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
@ -586,9 +588,9 @@ class EmailField(CharField):
validators.isValidEmail(field_data, all_data) validators.isValidEmail(field_data, all_data)
def formfield(self, **kwargs): def formfield(self, **kwargs):
defaults = {'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text} defaults = {'form_class': forms.EmailField}
defaults.update(kwargs) defaults.update(kwargs)
return forms.EmailField(**defaults) return super(EmailField, self).formfield(**defaults)
class FileField(Field): class FileField(Field):
def __init__(self, verbose_name=None, name=None, upload_to='', **kwargs): def __init__(self, verbose_name=None, name=None, upload_to='', **kwargs):
@ -723,9 +725,9 @@ class IntegerField(Field):
return [oldforms.IntegerField] return [oldforms.IntegerField]
def formfield(self, **kwargs): def formfield(self, **kwargs):
defaults = {'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text} defaults = {'form_class': forms.IntegerField}
defaults.update(kwargs) defaults.update(kwargs)
return forms.IntegerField(**defaults) return super(IntegerField, self).formfield(**defaults)
class IPAddressField(Field): class IPAddressField(Field):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
@ -762,9 +764,9 @@ class PhoneNumberField(IntegerField):
def formfield(self, **kwargs): def formfield(self, **kwargs):
from django.contrib.localflavor.us.forms import USPhoneNumberField from django.contrib.localflavor.us.forms import USPhoneNumberField
defaults = {'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text} defaults = {'form_class': USPhoneNumberField}
defaults.update(kwargs) defaults.update(kwargs)
return USPhoneNumberField(**defaults) return super(PhoneNumberField, self).formfield(**defaults)
class PositiveIntegerField(IntegerField): class PositiveIntegerField(IntegerField):
def get_manipulator_field_objs(self): def get_manipulator_field_objs(self):
@ -779,7 +781,7 @@ class SlugField(Field):
kwargs['maxlength'] = kwargs.get('maxlength', 50) kwargs['maxlength'] = kwargs.get('maxlength', 50)
kwargs.setdefault('validator_list', []).append(validators.isSlug) kwargs.setdefault('validator_list', []).append(validators.isSlug)
# Set db_index=True unless it's been set manually. # Set db_index=True unless it's been set manually.
if not kwargs.has_key('db_index'): if 'db_index' not in kwargs:
kwargs['db_index'] = True kwargs['db_index'] = True
Field.__init__(self, *args, **kwargs) Field.__init__(self, *args, **kwargs)
@ -795,9 +797,9 @@ class TextField(Field):
return [oldforms.LargeTextField] return [oldforms.LargeTextField]
def formfield(self, **kwargs): def formfield(self, **kwargs):
defaults = {'required': not self.blank, 'widget': forms.Textarea, 'label': capfirst(self.verbose_name), 'help_text': self.help_text} defaults = {'widget': forms.Textarea}
defaults.update(kwargs) defaults.update(kwargs)
return forms.CharField(**defaults) return super(TextField, self).formfield(**defaults)
class TimeField(Field): class TimeField(Field):
empty_strings_allowed = False empty_strings_allowed = False
@ -840,9 +842,9 @@ class TimeField(Field):
return {self.attname: (val is not None and val.strftime("%H:%M:%S") or '')} return {self.attname: (val is not None and val.strftime("%H:%M:%S") or '')}
def formfield(self, **kwargs): def formfield(self, **kwargs):
defaults = {'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text} defaults = {'form_class': forms.TimeField}
defaults.update(kwargs) defaults.update(kwargs)
return forms.TimeField(**defaults) return super(TimeField, self).formfield(**defaults)
class URLField(CharField): class URLField(CharField):
def __init__(self, verbose_name=None, name=None, verify_exists=True, **kwargs): def __init__(self, verbose_name=None, name=None, verify_exists=True, **kwargs):
@ -859,9 +861,9 @@ class URLField(CharField):
return "CharField" return "CharField"
def formfield(self, **kwargs): def formfield(self, **kwargs):
defaults = {'required': not self.blank, 'verify_exists': self.verify_exists, 'label': capfirst(self.verbose_name), 'help_text': self.help_text} defaults = {'form_class': forms.URLField, 'verify_exists': self.verify_exists}
defaults.update(kwargs) defaults.update(kwargs)
return forms.URLField(**defaults) return super(URLField, self).formfield(**defaults)
class USStateField(Field): class USStateField(Field):
def get_manipulator_field_objs(self): def get_manipulator_field_objs(self):

View File

@ -37,7 +37,7 @@ class GenericForeignKey(object):
def instance_pre_init(self, signal, sender, args, kwargs): def instance_pre_init(self, signal, sender, args, kwargs):
# Handle initalizing an object with the generic FK instaed of # Handle initalizing an object with the generic FK instaed of
# content-type/object-id fields. # content-type/object-id fields.
if kwargs.has_key(self.name): if self.name in kwargs:
value = kwargs.pop(self.name) value = kwargs.pop(self.name)
kwargs[self.ct_field] = self.get_content_type(value) kwargs[self.ct_field] = self.get_content_type(value)
kwargs[self.fk_field] = value._get_pk_val() kwargs[self.fk_field] = value._get_pk_val()

View File

@ -474,7 +474,7 @@ class ForeignKey(RelatedField, Field):
to_field = to_field or to._meta.pk.name to_field = to_field or to._meta.pk.name
kwargs['verbose_name'] = kwargs.get('verbose_name', '') kwargs['verbose_name'] = kwargs.get('verbose_name', '')
if kwargs.has_key('edit_inline_type'): if 'edit_inline_type' in kwargs:
import warnings import warnings
warnings.warn("edit_inline_type is deprecated. Use edit_inline instead.") warnings.warn("edit_inline_type is deprecated. Use edit_inline instead.")
kwargs['edit_inline'] = kwargs.pop('edit_inline_type') kwargs['edit_inline'] = kwargs.pop('edit_inline_type')
@ -553,9 +553,9 @@ class ForeignKey(RelatedField, Field):
setattr(cls, related.get_accessor_name(), ForeignRelatedObjectsDescriptor(related)) setattr(cls, related.get_accessor_name(), ForeignRelatedObjectsDescriptor(related))
def formfield(self, **kwargs): def formfield(self, **kwargs):
defaults = {'queryset': self.rel.to._default_manager.all(), 'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text} defaults = {'form_class': forms.ModelChoiceField, 'queryset': self.rel.to._default_manager.all()}
defaults.update(kwargs) defaults.update(kwargs)
return forms.ModelChoiceField(**defaults) return super(ForeignKey, self).formfield(**defaults)
class OneToOneField(RelatedField, IntegerField): class OneToOneField(RelatedField, IntegerField):
def __init__(self, to, to_field=None, **kwargs): def __init__(self, to, to_field=None, **kwargs):
@ -567,7 +567,7 @@ class OneToOneField(RelatedField, IntegerField):
to_field = to_field or to._meta.pk.name to_field = to_field or to._meta.pk.name
kwargs['verbose_name'] = kwargs.get('verbose_name', '') kwargs['verbose_name'] = kwargs.get('verbose_name', '')
if kwargs.has_key('edit_inline_type'): if 'edit_inline_type' in kwargs:
import warnings import warnings
warnings.warn("edit_inline_type is deprecated. Use edit_inline instead.") warnings.warn("edit_inline_type is deprecated. Use edit_inline instead.")
kwargs['edit_inline'] = kwargs.pop('edit_inline_type') kwargs['edit_inline'] = kwargs.pop('edit_inline_type')
@ -619,9 +619,9 @@ class OneToOneField(RelatedField, IntegerField):
cls._meta.one_to_one_field = self cls._meta.one_to_one_field = self
def formfield(self, **kwargs): def formfield(self, **kwargs):
defaults = {'queryset': self.rel.to._default_manager.all(), 'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text} defaults = {'form_class': forms.ModelChoiceField, 'queryset': self.rel.to._default_manager.all()}
defaults.update(kwargs) defaults.update(kwargs)
return forms.ModelChoiceField(**defaults) return super(OneToOneField, self).formfield(**defaults)
class ManyToManyField(RelatedField, Field): class ManyToManyField(RelatedField, Field):
def __init__(self, to, **kwargs): def __init__(self, to, **kwargs):
@ -738,13 +738,13 @@ class ManyToManyField(RelatedField, Field):
return getattr(obj, self.attname).all() return getattr(obj, self.attname).all()
def formfield(self, **kwargs): def formfield(self, **kwargs):
defaults = {'form_class': forms.ModelMultipleChoiceField, 'queryset': self.rel.to._default_manager.all()}
defaults.update(kwargs)
# If initial is passed in, it's a list of related objects, but the # If initial is passed in, it's a list of related objects, but the
# MultipleChoiceField takes a list of IDs. # MultipleChoiceField takes a list of IDs.
if kwargs.get('initial') is not None: if defaults.get('initial') is not None:
kwargs['initial'] = [i._get_pk_val() for i in kwargs['initial']] defaults['initial'] = [i._get_pk_val() for i in defaults['initial']]
defaults = {'queryset' : self.rel.to._default_manager.all(), 'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text} return super(ManyToManyField, self).formfield(**defaults)
defaults.update(kwargs)
return forms.ModelMultipleChoiceField(**defaults)
class ManyToOneRel(object): class ManyToOneRel(object):
def __init__(self, to, field_name, num_in_admin=3, min_num_in_admin=None, def __init__(self, to, field_name, num_in_admin=3, min_num_in_admin=None,

View File

@ -103,7 +103,7 @@ def register_models(app_label, *models):
# in the _app_models dictionary # in the _app_models dictionary
model_name = model._meta.object_name.lower() model_name = model._meta.object_name.lower()
model_dict = _app_models.setdefault(app_label, {}) model_dict = _app_models.setdefault(app_label, {})
if model_dict.has_key(model_name): if model_name in model_dict:
# The same model may be imported via different paths (e.g. # The same model may be imported via different paths (e.g.
# appname.models and project.appname.models). We use the source # appname.models and project.appname.models). We use the source
# filename as a means to detect identity. # filename as a means to detect identity.

View File

@ -140,7 +140,7 @@ class Options(object):
def get_follow(self, override=None): def get_follow(self, override=None):
follow = {} follow = {}
for f in self.fields + self.many_to_many + self.get_all_related_objects(): for f in self.fields + self.many_to_many + self.get_all_related_objects():
if override and override.has_key(f.name): if override and f.name in override:
child_override = override[f.name] child_override = override[f.name]
else: else:
child_override = None child_override = None
@ -182,7 +182,7 @@ class Options(object):
# TODO: follow # TODO: follow
if not hasattr(self, '_field_types'): if not hasattr(self, '_field_types'):
self._field_types = {} self._field_types = {}
if not self._field_types.has_key(field_type): if field_type not in self._field_types:
try: try:
# First check self.fields. # First check self.fields.
for f in self.fields: for f in self.fields:

View File

@ -46,12 +46,12 @@ def enter_transaction_management():
when no current block is running). when no current block is running).
""" """
thread_ident = thread.get_ident() thread_ident = thread.get_ident()
if state.has_key(thread_ident) and state[thread_ident]: if thread_ident in state and state[thread_ident]:
state[thread_ident].append(state[thread_ident][-1]) state[thread_ident].append(state[thread_ident][-1])
else: else:
state[thread_ident] = [] state[thread_ident] = []
state[thread_ident].append(settings.TRANSACTIONS_MANAGED) state[thread_ident].append(settings.TRANSACTIONS_MANAGED)
if not dirty.has_key(thread_ident): if thread_ident not in dirty:
dirty[thread_ident] = False dirty[thread_ident] = False
def leave_transaction_management(): def leave_transaction_management():
@ -61,7 +61,7 @@ def leave_transaction_management():
those from outside. (Commits are on connection level.) those from outside. (Commits are on connection level.)
""" """
thread_ident = thread.get_ident() thread_ident = thread.get_ident()
if state.has_key(thread_ident) and state[thread_ident]: if thread_ident in state and state[thread_ident]:
del state[thread_ident][-1] del state[thread_ident][-1]
else: else:
raise TransactionManagementError("This code isn't under transaction management") raise TransactionManagementError("This code isn't under transaction management")
@ -84,7 +84,7 @@ def set_dirty():
changes waiting for commit. changes waiting for commit.
""" """
thread_ident = thread.get_ident() thread_ident = thread.get_ident()
if dirty.has_key(thread_ident): if thread_ident in dirty:
dirty[thread_ident] = True dirty[thread_ident] = True
else: else:
raise TransactionManagementError("This code isn't under transaction management") raise TransactionManagementError("This code isn't under transaction management")
@ -96,7 +96,7 @@ def set_clean():
should happen. should happen.
""" """
thread_ident = thread.get_ident() thread_ident = thread.get_ident()
if dirty.has_key(thread_ident): if thread_ident in dirty:
dirty[thread_ident] = False dirty[thread_ident] = False
else: else:
raise TransactionManagementError("This code isn't under transaction management") raise TransactionManagementError("This code isn't under transaction management")
@ -106,7 +106,7 @@ def is_managed():
Checks whether the transaction manager is in manual or in auto state. Checks whether the transaction manager is in manual or in auto state.
""" """
thread_ident = thread.get_ident() thread_ident = thread.get_ident()
if state.has_key(thread_ident): if thread_ident in state:
if state[thread_ident]: if state[thread_ident]:
return state[thread_ident][-1] return state[thread_ident][-1]
return settings.TRANSACTIONS_MANAGED return settings.TRANSACTIONS_MANAGED

View File

@ -29,12 +29,12 @@ class HttpRequest(object):
def __getitem__(self, key): def __getitem__(self, key):
for d in (self.POST, self.GET): for d in (self.POST, self.GET):
if d.has_key(key): if key in d:
return d[key] return d[key]
raise KeyError, "%s not found in either POST or GET" % key raise KeyError, "%s not found in either POST or GET" % key
def has_key(self, key): def has_key(self, key):
return self.GET.has_key(key) or self.POST.has_key(key) return key in self.GET or key in self.POST
def get_full_path(self): def get_full_path(self):
return '' return ''
@ -57,7 +57,7 @@ def parse_file_upload(header_dict, post_data):
# name_dict is something like {'name': 'file', 'filename': 'test.txt'} for file uploads # name_dict is something like {'name': 'file', 'filename': 'test.txt'} for file uploads
# or {'name': 'blah'} for POST fields # or {'name': 'blah'} for POST fields
# We assume all uploaded files have a 'filename' set. # We assume all uploaded files have a 'filename' set.
if name_dict.has_key('filename'): if 'filename' in name_dict:
assert type([]) != type(submessage.get_payload()), "Nested MIME messages are not supported" assert type([]) != type(submessage.get_payload()), "Nested MIME messages are not supported"
if not name_dict['filename'].strip(): if not name_dict['filename'].strip():
continue continue
@ -66,7 +66,7 @@ def parse_file_upload(header_dict, post_data):
filename = name_dict['filename'][name_dict['filename'].rfind("\\")+1:] filename = name_dict['filename'][name_dict['filename'].rfind("\\")+1:]
FILES.appendlist(name_dict['name'], { FILES.appendlist(name_dict['name'], {
'filename': filename, 'filename': filename,
'content-type': (submessage.has_key('Content-Type') and submessage['Content-Type'] or None), 'content-type': 'Content-Type' in submessage and submessage['Content-Type'] or None,
'content': submessage.get_payload(), 'content': submessage.get_payload(),
}) })
else: else:

View File

@ -25,7 +25,7 @@ class CommonMiddleware(object):
""" """
# Check for denied User-Agents # Check for denied User-Agents
if request.META.has_key('HTTP_USER_AGENT'): if 'HTTP_USER_AGENT' in request.META:
for user_agent_regex in settings.DISALLOWED_USER_AGENTS: for user_agent_regex in settings.DISALLOWED_USER_AGENTS:
if user_agent_regex.search(request.META['HTTP_USER_AGENT']): if user_agent_regex.search(request.META['HTTP_USER_AGENT']):
return http.HttpResponseForbidden('<h1>Forbidden</h1>') return http.HttpResponseForbidden('<h1>Forbidden</h1>')

View File

@ -457,7 +457,7 @@ class MultiValueField(Field):
for i, field in enumerate(self.fields): for i, field in enumerate(self.fields):
try: try:
field_value = value[i] field_value = value[i]
except KeyError: except IndexError:
field_value = None field_value = None
if self.required and field_value in EMPTY_VALUES: if self.required and field_value in EMPTY_VALUES:
raise ValidationError(ugettext(u'This field is required.')) raise ValidationError(ugettext(u'This field is required.'))

View File

@ -122,7 +122,14 @@ class BaseForm(StrAndUnicode):
else: else:
if errors_on_separate_row and bf_errors: if errors_on_separate_row and bf_errors:
output.append(error_row % bf_errors) output.append(error_row % bf_errors)
label = bf.label and bf.label_tag(escape(bf.label + ':')) or '' if bf.label:
label = escape(bf.label)
# Only add a colon if the label does not end in punctuation.
if label[-1] not in ':?.!':
label += ':'
label = bf.label_tag(label) or ''
else:
label = ''
if field.help_text: if field.help_text:
help_text = help_text_html % field.help_text help_text = help_text_html % field.help_text
else: else:
@ -244,7 +251,7 @@ class BoundField(StrAndUnicode):
def as_widget(self, widget, attrs=None): def as_widget(self, widget, attrs=None):
attrs = attrs or {} attrs = attrs or {}
auto_id = self.auto_id auto_id = self.auto_id
if auto_id and not attrs.has_key('id') and not widget.attrs.has_key('id'): if auto_id and 'id' not in attrs and 'id' not in widget.attrs:
attrs['id'] = auto_id attrs['id'] = auto_id
if not self.form.is_bound: if not self.form.is_bound:
data = self.form.initial.get(self.name, self.field.initial) data = self.form.initial.get(self.name, self.field.initial)

View File

@ -230,7 +230,7 @@ class RadioInput(StrAndUnicode):
return self.value == self.choice_value return self.value == self.choice_value
def tag(self): def tag(self):
if self.attrs.has_key('id'): if 'id' in self.attrs:
self.attrs['id'] = '%s_%s' % (self.attrs['id'], self.index) self.attrs['id'] = '%s_%s' % (self.attrs['id'], self.index)
final_attrs = dict(self.attrs, type='radio', name=self.name, value=self.choice_value) final_attrs = dict(self.attrs, type='radio', name=self.name, value=self.choice_value)
if self.is_checked(): if self.is_checked():
@ -276,7 +276,7 @@ class RadioSelect(Select):
class CheckboxSelectMultiple(SelectMultiple): class CheckboxSelectMultiple(SelectMultiple):
def render(self, name, value, attrs=None, choices=()): def render(self, name, value, attrs=None, choices=()):
if value is None: value = [] if value is None: value = []
has_id = attrs and attrs.has_key('id') has_id = attrs and 'id' in attrs
final_attrs = self.build_attrs(attrs, name=name) final_attrs = self.build_attrs(attrs, name=name)
output = [u'<ul>'] output = [u'<ul>']
str_values = set([smart_unicode(v) for v in value]) # Normalize to strings. str_values = set([smart_unicode(v) for v in value]) # Normalize to strings.
@ -347,7 +347,7 @@ class MultiWidget(Widget):
id_for_label = classmethod(id_for_label) id_for_label = classmethod(id_for_label)
def value_from_datadict(self, data, name): def value_from_datadict(self, data, name):
return [data.get(name + '_%s' % i) for i in range(len(self.widgets))] return [widget.value_from_datadict(data, name + '_%s' % i) for i, widget in enumerate(self.widgets)]
def format_output(self, rendered_widgets): def format_output(self, rendered_widgets):
return u''.join(rendered_widgets) return u''.join(rendered_widgets)

View File

@ -341,7 +341,7 @@ class FormField(object):
def convert_post_data(self, new_data): def convert_post_data(self, new_data):
name = self.get_member_name() name = self.get_member_name()
if new_data.has_key(self.field_name): if self.field_name in new_data:
d = new_data.getlist(self.field_name) d = new_data.getlist(self.field_name)
try: try:
converted_data = [self.__class__.html2python(data) for data in d] converted_data = [self.__class__.html2python(data) for data in d]

View File

@ -201,18 +201,27 @@ class Lexer(object):
def tokenize(self): def tokenize(self):
"Return a list of tokens from a given template_string" "Return a list of tokens from a given template_string"
# remove all empty strings, because the regex has a tendency to add them in_tag = False
bits = filter(None, tag_re.split(self.template_string)) result = []
return map(self.create_token, bits) for bit in tag_re.split(self.template_string):
if bit:
result.append(self.create_token(bit, in_tag))
in_tag = not in_tag
return result
def create_token(self,token_string): def create_token(self, token_string, in_tag):
"Convert the given token string into a new Token object and return it" """
if token_string.startswith(VARIABLE_TAG_START): Convert the given token string into a new Token object and return it.
token = Token(TOKEN_VAR, token_string[len(VARIABLE_TAG_START):-len(VARIABLE_TAG_END)].strip()) If in_tag is True, we are processing something that matched a tag,
elif token_string.startswith(BLOCK_TAG_START): otherwise it should be treated as a literal string.
token = Token(TOKEN_BLOCK, token_string[len(BLOCK_TAG_START):-len(BLOCK_TAG_END)].strip()) """
elif token_string.startswith(COMMENT_TAG_START): if in_tag:
token = Token(TOKEN_COMMENT, '') if token_string.startswith(VARIABLE_TAG_START):
token = Token(TOKEN_VAR, token_string[len(VARIABLE_TAG_START):-len(VARIABLE_TAG_END)].strip())
elif token_string.startswith(BLOCK_TAG_START):
token = Token(TOKEN_BLOCK, token_string[len(BLOCK_TAG_START):-len(BLOCK_TAG_END)].strip())
elif token_string.startswith(COMMENT_TAG_START):
token = Token(TOKEN_COMMENT, '')
else: else:
token = Token(TOKEN_TEXT, token_string) token = Token(TOKEN_TEXT, token_string)
return token return token
@ -223,22 +232,22 @@ class DebugLexer(Lexer):
def tokenize(self): def tokenize(self):
"Return a list of tokens from a given template_string" "Return a list of tokens from a given template_string"
token_tups, upto = [], 0 result, upto = [], 0
for match in tag_re.finditer(self.template_string): for match in tag_re.finditer(self.template_string):
start, end = match.span() start, end = match.span()
if start > upto: if start > upto:
token_tups.append( (self.template_string[upto:start], (upto, start)) ) result.append(self.create_token(self.template_string[upto:start], (upto, start), False))
upto = start upto = start
token_tups.append( (self.template_string[start:end], (start,end)) ) result.append(self.create_token(self.template_string[start:end], (start, end), True))
upto = end upto = end
last_bit = self.template_string[upto:] last_bit = self.template_string[upto:]
if last_bit: if last_bit:
token_tups.append( (last_bit, (upto, upto + len(last_bit))) ) result.append(self.create_token(last_bit, (upto, upto + len(last_bit)), False))
return [self.create_token(tok, (self.origin, loc)) for tok, loc in token_tups] return result
def create_token(self, token_string, source): def create_token(self, token_string, source, in_tag):
token = super(DebugLexer, self).create_token(token_string) token = super(DebugLexer, self).create_token(token_string, in_tag)
token.source = source token.source = self.origin, source
return token return token
class Parser(object): class Parser(object):
@ -346,7 +355,7 @@ class Parser(object):
return FilterExpression(token, self) return FilterExpression(token, self)
def find_filter(self, filter_name): def find_filter(self, filter_name):
if self.filters.has_key(filter_name): if filter_name in self.filters:
return self.filters[filter_name] return self.filters[filter_name]
else: else:
raise TemplateSyntaxError, "Invalid filter: '%s'" % filter_name raise TemplateSyntaxError, "Invalid filter: '%s'" % filter_name

View File

@ -35,7 +35,7 @@ class Context(object):
def __getitem__(self, key): def __getitem__(self, key):
"Get a variable's value, starting at the current context and going upward" "Get a variable's value, starting at the current context and going upward"
for d in self.dicts: for d in self.dicts:
if d.has_key(key): if key in d:
return d[key] return d[key]
raise KeyError(key) raise KeyError(key)
@ -45,7 +45,7 @@ class Context(object):
def has_key(self, key): def has_key(self, key):
for d in self.dicts: for d in self.dicts:
if d.has_key(key): if key in d:
return True return True
return False return False
@ -54,7 +54,7 @@ class Context(object):
def get(self, key, otherwise=None): def get(self, key, otherwise=None):
for d in self.dicts: for d in self.dicts:
if d.has_key(key): if key in d:
return d[key] return d[key]
return otherwise return otherwise

View File

@ -88,7 +88,7 @@ class ForNode(Node):
def render(self, context): def render(self, context):
nodelist = NodeList() nodelist = NodeList()
if context.has_key('forloop'): if 'forloop' in context:
parentloop = context['forloop'] parentloop = context['forloop']
else: else:
parentloop = {} parentloop = {}
@ -134,7 +134,7 @@ class IfChangedNode(Node):
self._varlist = varlist self._varlist = varlist
def render(self, context): def render(self, context):
if context.has_key('forloop') and context['forloop']['first']: if 'forloop' in context and context['forloop']['first']:
self._last_seen = None self._last_seen = None
try: try:
if self._varlist: if self._varlist:
@ -433,7 +433,7 @@ def cycle(parser, token):
name = args[1] name = args[1]
if not hasattr(parser, '_namedCycleNodes'): if not hasattr(parser, '_namedCycleNodes'):
raise TemplateSyntaxError("No named cycles in template: '%s' is not defined" % name) raise TemplateSyntaxError("No named cycles in template: '%s' is not defined" % name)
if not parser._namedCycleNodes.has_key(name): if name not in parser._namedCycleNodes:
raise TemplateSyntaxError("Named cycle '%s' does not exist" % name) raise TemplateSyntaxError("Named cycle '%s' does not exist" % name)
return parser._namedCycleNodes[name] return parser._namedCycleNodes[name]
@ -912,7 +912,7 @@ def templatetag(parser, token):
if len(bits) != 2: if len(bits) != 2:
raise TemplateSyntaxError, "'templatetag' statement takes one argument" raise TemplateSyntaxError, "'templatetag' statement takes one argument"
tag = bits[1] tag = bits[1]
if not TemplateTagNode.mapping.has_key(tag): if tag not in TemplateTagNode.mapping:
raise TemplateSyntaxError, "Invalid templatetag argument: '%s'. Must be one of: %s" % \ raise TemplateSyntaxError, "Invalid templatetag argument: '%s'. Must be one of: %s" % \
(tag, TemplateTagNode.mapping.keys()) (tag, TemplateTagNode.mapping.keys())
return TemplateTagNode(tag) return TemplateTagNode(tag)

View File

@ -42,7 +42,7 @@ class MergeDict(object):
def has_key(self, key): def has_key(self, key):
for dict in self.dicts: for dict in self.dicts:
if dict.has_key(key): if key in dict:
return True return True
return False return False

View File

@ -42,7 +42,7 @@ def lazy(func, *resultclasses):
res = self.__func(*self.__args, **self.__kw) res = self.__func(*self.__args, **self.__kw)
return self.__dispatch[type(res)][funcname](res, *args, **kw) return self.__dispatch[type(res)][funcname](res, *args, **kw)
if not self.__dispatch.has_key(klass): if klass not in self.__dispatch:
self.__dispatch[klass] = {} self.__dispatch[klass] = {}
self.__dispatch[klass][funcname] = func self.__dispatch[klass][funcname] = func
return __wrapper__ return __wrapper__

View File

@ -200,7 +200,7 @@ def deactivate():
will resolve against the default translation object, again. will resolve against the default translation object, again.
""" """
global _active global _active
if _active.has_key(currentThread()): if currentThread() in _active:
del _active[currentThread()] del _active[currentThread()]
def get_language(): def get_language():

View File

@ -97,7 +97,7 @@ def javascript_catalog(request, domain='djangojs', packages=None):
deliver your JavaScript source from Django templates. deliver your JavaScript source from Django templates.
""" """
if request.GET: if request.GET:
if request.GET.has_key('language'): if 'language' in request.GET:
if check_for_language(request.GET['language']): if check_for_language(request.GET['language']):
activate(request.GET['language']) activate(request.GET['language'])
if packages is None: if packages is None:
@ -136,7 +136,7 @@ def javascript_catalog(request, domain='djangojs', packages=None):
t.update(catalog._catalog) t.update(catalog._catalog)
src = [LibHead] src = [LibHead]
plural = None plural = None
if t.has_key(''): if '' in t:
for l in t[''].split('\n'): for l in t[''].split('\n'):
if l.startswith('Plural-Forms:'): if l.startswith('Plural-Forms:'):
plural = l.split(':',1)[1].strip() plural = l.split(':',1)[1].strip()
@ -155,7 +155,7 @@ def javascript_catalog(request, domain='djangojs', packages=None):
if type(k) in (str, unicode): if type(k) in (str, unicode):
csrc.append("catalog['%s'] = '%s';\n" % (javascript_quote(k), javascript_quote(v))) csrc.append("catalog['%s'] = '%s';\n" % (javascript_quote(k), javascript_quote(v)))
elif type(k) == tuple: elif type(k) == tuple:
if not pdict.has_key(k[0]): if k[0] not in pdict:
pdict[k[0]] = k[1] pdict[k[0]] = k[1]
else: else:
pdict[k[0]] = max(k[1], pdict[k[0]]) pdict[k[0]] = max(k[1], pdict[k[0]])

View File

@ -208,7 +208,8 @@ Hashtype is either ``sha1`` (default), ``md5`` or ``crypt`` -- the algorithm
used to perform a one-way hash of the password. Salt is a random string used used to perform a one-way hash of the password. Salt is a random string used
to salt the raw password to create the hash. Note that the ``crypt`` method is to salt the raw password to create the hash. Note that the ``crypt`` method is
only supported on platforms that have the standard Python ``crypt`` module only supported on platforms that have the standard Python ``crypt`` module
available. available, and ``crypt`` support is only available in the Django development
version.
For example:: For example::

View File

@ -112,7 +112,7 @@ the previous record in the database::
b4 = Blog(id=3, name='Not Cheddar', tagline='Anything but cheese.') b4 = Blog(id=3, name='Not Cheddar', tagline='Anything but cheese.')
b4.save() # Overrides the previous blog with ID=3! b4.save() # Overrides the previous blog with ID=3!
See _`How Django knows to UPDATE vs. INSERT`, below, for the reason this See `How Django knows to UPDATE vs. INSERT`_, below, for the reason this
happens. happens.
Explicitly specifying auto-primary-key values is mostly useful for bulk-saving Explicitly specifying auto-primary-key values is mostly useful for bulk-saving
@ -714,7 +714,7 @@ QuerySet methods that do not return QuerySets
The following ``QuerySet`` methods evaluate the ``QuerySet`` and return The following ``QuerySet`` methods evaluate the ``QuerySet`` and return
something *other than* a ``QuerySet``. something *other than* a ``QuerySet``.
These methods do not use a cache (see _`Caching and QuerySets` below). Rather, These methods do not use a cache (see `Caching and QuerySets`_ below). Rather,
they query the database each time they're called. they query the database each time they're called.
``get(**kwargs)`` ``get(**kwargs)``
@ -906,8 +906,8 @@ The database API supports the following lookup types:
exact exact
~~~~~ ~~~~~
Exact match. If the value provided for comparison is ``None``, it will Exact match. If the value provided for comparison is ``None``, it will
be interpreted as an SQL ``NULL`` (See isnull_ for more details). be interpreted as an SQL ``NULL`` (See isnull_ for more details).
Examples:: Examples::

View File

@ -19,13 +19,22 @@ In two lines::
send_mail('Subject here', 'Here is the message.', 'from@example.com', send_mail('Subject here', 'Here is the message.', 'from@example.com',
['to@example.com'], fail_silently=False) ['to@example.com'], fail_silently=False)
Mail will be sent using the SMTP host and port specified in the `EMAIL_HOST`_
and `EMAIL_PORT`_ settings. The `EMAIL_HOST_USER`_ and `EMAIL_HOST_PASSWORD`_
settings, if set, will be used to authenticate to the SMTP server.
.. note:: .. note::
The character set of email sent with ``django.core.mail`` will be set to The character set of email sent with ``django.core.mail`` will be set to
the value of your `DEFAULT_CHARSET setting`_. the value of your `DEFAULT_CHARSET setting`_.
.. _DEFAULT_CHARSET setting: ../settings/#DEFAULT_CHARSET .. _DEFAULT_CHARSET setting: ../settings/#default-charset
.. _EMAIL_HOST: ../settings/#email-host
.. _EMAIL_PORT: ../settings/#email-port
.. _EMAIL_HOST_USER: ../settings/#email-host-user
.. _EMAIL_HOST_PASSWORD: ../settings/#email-host-password
send_mail() send_mail()
=========== ===========

View File

@ -517,7 +517,7 @@ to put punctuation at the end of your validation messages.
When are validators called? When are validators called?
--------------------------- ---------------------------
After a form has been submitted, Django validates each field in turn. First, After a form has been submitted, Django validates each field in turn. First,
if the field is required, Django checks that it is present and non-empty. Then, if the field is required, Django checks that it is present and non-empty. Then,
if that test passes *and the form submission contained data* for that field, all if that test passes *and the form submission contained data* for that field, all
the validators for that field are called in turn. The emphasized portion in the the validators for that field are called in turn. The emphasized portion in the
@ -615,15 +615,19 @@ fails. If no message is passed in, a default message is used.
``other_value``, then the validators in ``validator_list`` are all run ``other_value``, then the validators in ``validator_list`` are all run
against the current field. against the current field.
``RequiredIfOtherFieldGiven``
Takes a field name of the current field is only required if the other
field has a value.
``RequiredIfOtherFieldsGiven``
Similar to ``RequiredIfOtherFieldGiven``, except that it takes a list of
field names and if any one of the supplied fields has a value provided,
the current field being validated is required.
``RequiredIfOtherFieldNotGiven`` ``RequiredIfOtherFieldNotGiven``
Takes the name of the other field and this field is only required if the Takes the name of the other field and this field is only required if the
other field has no value. other field has no value.
``RequiredIfOtherFieldsNotGiven``
Similar to ``RequiredIfOtherFieldNotGiven``, except that it takes a list
of field names and if any one of the supplied fields does not have a value
provided, the field being validated is required.
``RequiredIfOtherFieldEquals`` and ``RequiredIfOtherFieldDoesNotEqual`` ``RequiredIfOtherFieldEquals`` and ``RequiredIfOtherFieldDoesNotEqual``
Each of these validator classes takes a field name and a value (in that Each of these validator classes takes a field name and a value (in that
order). If the given field does (or does not have, in the latter case) the order). If the given field does (or does not have, in the latter case) the
@ -650,8 +654,8 @@ fails. If no message is passed in, a default message is used.
``NumberIsInRange`` ``NumberIsInRange``
Takes two boundary numbers, ``lower`` and ``upper``, and checks that the Takes two boundary numbers, ``lower`` and ``upper``, and checks that the
field is greater than ``lower`` (if given) and less than ``upper`` (if field is greater than ``lower`` (if given) and less than ``upper`` (if
given). given).
Both checks are inclusive. That is, ``NumberIsInRange(10, 20)`` will allow Both checks are inclusive. That is, ``NumberIsInRange(10, 20)`` will allow
values of both 10 and 20. This validator only checks numeric values values of both 10 and 20. This validator only checks numeric values
(e.g., float and integer values). (e.g., float and integer values).

View File

@ -45,16 +45,16 @@ Get your database running
========================= =========================
If you plan to use Django's database API functionality, you'll need to If you plan to use Django's database API functionality, you'll need to
make sure a database server is running. Django works with PostgreSQL_ make sure a database server is running. Django works with PostgreSQL_,
(recommended), MySQL_ and SQLite_. MySQL_ and SQLite_.
Additionally, you'll need to make sure your Python database bindings are Additionally, you'll need to make sure your Python database bindings are
installed. installed.
* If you're using PostgreSQL, you'll need the psycopg_ package (version 2 is * If you're using PostgreSQL, you'll need the psycopg_ package. Django supports
recommended with ``postgresql_psycopg2`` backend, version 1.1 works also with the both version 1 and 2. (When you configure Django's database layer, specify
``postgresql``` backend). either ``postgresql`` [for version 1] or ``postgresql_psycopg2`` [for version 2].)
If you're on Windows, check out the unofficial `compiled Windows version`_. If you're on Windows, check out the unofficial `compiled Windows version`_.
* If you're using MySQL, you'll need MySQLdb_, version 1.2.1p2 or higher. * If you're using MySQL, you'll need MySQLdb_, version 1.2.1p2 or higher.

View File

@ -395,8 +395,10 @@ EMAIL_HOST_PASSWORD
Default: ``''`` (Empty string) Default: ``''`` (Empty string)
Username to use for the SMTP server defined in ``EMAIL_HOST``. If empty, Password to use for the SMTP server defined in ``EMAIL_HOST``. This setting is
Django won't attempt authentication. used in conjunction with ``EMAIL_HOST_USER`` when authenticating to the SMTP
server. If either of these settings is empty, Django won't attempt
authenticaion.
See also ``EMAIL_HOST_USER``. See also ``EMAIL_HOST_USER``.
@ -570,9 +572,23 @@ strings for translation, but the translation won't happen at runtime -- so
you'll have to remember to wrap the languages in the *real* ``gettext()`` in you'll have to remember to wrap the languages in the *real* ``gettext()`` in
any code that uses ``LANGUAGES`` at runtime. any code that uses ``LANGUAGES`` at runtime.
LOGIN_REDIRECT_URL
------------------
**New in Django development version**
Default: ``'/accounts/profile/'``
The URL where requests are redirected after login when the
``contrib.auth.login`` view gets no ``next`` parameter.
This is used by the `@login_required`_ decorator, for example.
LOGIN_URL LOGIN_URL
--------- ---------
**New in Django development version**
Default: ``'/accounts/login/'`` Default: ``'/accounts/login/'``
The URL where requests are redirected for login, specially when using the The URL where requests are redirected for login, specially when using the
@ -581,6 +597,8 @@ The URL where requests are redirected for login, specially when using the
LOGOUT_URL LOGOUT_URL
---------- ----------
**New in Django development version**
Default: ``'/accounts/logout/'`` Default: ``'/accounts/logout/'``
LOGIN_URL counterpart. LOGIN_URL counterpart.
@ -643,16 +661,6 @@ locales have different formats. For example, U.S. English would say
See `allowed date format strings`_. See also DATE_FORMAT, DATETIME_FORMAT, See `allowed date format strings`_. See also DATE_FORMAT, DATETIME_FORMAT,
TIME_FORMAT and YEAR_MONTH_FORMAT. TIME_FORMAT and YEAR_MONTH_FORMAT.
LOGIN_REDIRECT_URL
------------------
Default: ``'/accounts/profile/'``
The URL where requests are redirected after login when the
``contrib.auth.login`` view gets no ``next`` parameter.
This is used by the `@login_required`_ decorator, for example.
PREPEND_WWW PREPEND_WWW
----------- -----------

View File

@ -24,6 +24,12 @@ a commit=True parameter.
from django.db import models from django.db import models
ARTICLE_STATUS = (
(1, 'Draft'),
(2, 'Pending'),
(3, 'Live'),
)
class Category(models.Model): class Category(models.Model):
name = models.CharField(maxlength=20) name = models.CharField(maxlength=20)
url = models.CharField('The URL', maxlength=40) url = models.CharField('The URL', maxlength=40)
@ -44,6 +50,7 @@ class Article(models.Model):
writer = models.ForeignKey(Writer) writer = models.ForeignKey(Writer)
article = models.TextField() article = models.TextField()
categories = models.ManyToManyField(Category, blank=True) categories = models.ManyToManyField(Category, blank=True)
status = models.IntegerField(choices=ARTICLE_STATUS, blank=True, null=True)
def save(self): def save(self):
import datetime import datetime
@ -147,8 +154,8 @@ Create a couple of Writers.
>>> w = Writer(name='Bob Woodward') >>> w = Writer(name='Bob Woodward')
>>> w.save() >>> w.save()
ManyToManyFields are represented by a MultipleChoiceField, and ForeignKeys are ManyToManyFields are represented by a MultipleChoiceField, ForeignKeys and any
represented by a ChoiceField. fields with the 'choices' attribute are represented by a ChoiceField.
>>> ArticleForm = form_for_model(Article) >>> ArticleForm = form_for_model(Article)
>>> f = ArticleForm(auto_id=False) >>> f = ArticleForm(auto_id=False)
>>> print f >>> print f
@ -160,6 +167,12 @@ represented by a ChoiceField.
<option value="2">Bob Woodward</option> <option value="2">Bob Woodward</option>
</select></td></tr> </select></td></tr>
<tr><th>Article:</th><td><textarea rows="10" cols="40" name="article"></textarea></td></tr> <tr><th>Article:</th><td><textarea rows="10" cols="40" name="article"></textarea></td></tr>
<tr><th>Status:</th><td><select name="status">
<option value="" selected="selected">---------</option>
<option value="1">Draft</option>
<option value="2">Pending</option>
<option value="3">Live</option>
</select></td></tr>
<tr><th>Categories:</th><td><select multiple="multiple" name="categories"> <tr><th>Categories:</th><td><select multiple="multiple" name="categories">
<option value="1">Entertainment</option> <option value="1">Entertainment</option>
<option value="2">It&#39;s a test</option> <option value="2">It&#39;s a test</option>
@ -200,6 +213,12 @@ current values are inserted as 'initial' data in each Field.
<option value="2">Bob Woodward</option> <option value="2">Bob Woodward</option>
</select></li> </select></li>
<li>Article: <textarea rows="10" cols="40" name="article">Hello.</textarea></li> <li>Article: <textarea rows="10" cols="40" name="article">Hello.</textarea></li>
<li>Status: <select name="status">
<option value="" selected="selected">---------</option>
<option value="1">Draft</option>
<option value="2">Pending</option>
<option value="3">Live</option>
</select></li>
<li>Categories: <select multiple="multiple" name="categories"> <li>Categories: <select multiple="multiple" name="categories">
<option value="1">Entertainment</option> <option value="1">Entertainment</option>
<option value="2">It&#39;s a test</option> <option value="2">It&#39;s a test</option>
@ -232,6 +251,12 @@ Add some categories and test the many-to-many form output.
<option value="2">Bob Woodward</option> <option value="2">Bob Woodward</option>
</select></li> </select></li>
<li>Article: <textarea rows="10" cols="40" name="article">Hello.</textarea></li> <li>Article: <textarea rows="10" cols="40" name="article">Hello.</textarea></li>
<li>Status: <select name="status">
<option value="" selected="selected">---------</option>
<option value="1">Draft</option>
<option value="2">Pending</option>
<option value="3">Live</option>
</select></li>
<li>Categories: <select multiple="multiple" name="categories"> <li>Categories: <select multiple="multiple" name="categories">
<option value="1" selected="selected">Entertainment</option> <option value="1" selected="selected">Entertainment</option>
<option value="2">It&#39;s a test</option> <option value="2">It&#39;s a test</option>
@ -310,6 +335,12 @@ the data in the database when the form is instantiated.
<option value="2">Bob Woodward</option> <option value="2">Bob Woodward</option>
</select></li> </select></li>
<li>Article: <textarea rows="10" cols="40" name="article"></textarea></li> <li>Article: <textarea rows="10" cols="40" name="article"></textarea></li>
<li>Status: <select name="status">
<option value="" selected="selected">---------</option>
<option value="1">Draft</option>
<option value="2">Pending</option>
<option value="3">Live</option>
</select></li>
<li>Categories: <select multiple="multiple" name="categories"> <li>Categories: <select multiple="multiple" name="categories">
<option value="1">Entertainment</option> <option value="1">Entertainment</option>
<option value="2">It&#39;s a test</option> <option value="2">It&#39;s a test</option>
@ -329,6 +360,12 @@ the data in the database when the form is instantiated.
<option value="3">Carl Bernstein</option> <option value="3">Carl Bernstein</option>
</select></li> </select></li>
<li>Article: <textarea rows="10" cols="40" name="article"></textarea></li> <li>Article: <textarea rows="10" cols="40" name="article"></textarea></li>
<li>Status: <select name="status">
<option value="" selected="selected">---------</option>
<option value="1">Draft</option>
<option value="2">Pending</option>
<option value="3">Live</option>
</select></li>
<li>Categories: <select multiple="multiple" name="categories"> <li>Categories: <select multiple="multiple" name="categories">
<option value="1">Entertainment</option> <option value="1">Entertainment</option>
<option value="2">It&#39;s a test</option> <option value="2">It&#39;s a test</option>

View File

@ -55,8 +55,10 @@ class Tester(unittest.TestCase):
for t in self.ts: for t in self.ts:
if hasattr(t, 'x'): if hasattr(t, 'x'):
self.assert_(sd.has_key(safeRef(t.x))) self.assert_(sd.has_key(safeRef(t.x)))
self.assert_(safeRef(t.x) in sd)
else: else:
self.assert_(sd.has_key(safeRef(t))) self.assert_(sd.has_key(safeRef(t)))
self.assert_(safeRef(t) in sd)
def testRepresentation (self): def testRepresentation (self):
"""Test that the reference object's representation works """Test that the reference object's representation works

File diff suppressed because one or more lines are too long

View File

@ -5,6 +5,7 @@ from regressions import regression_tests
form_tests = r""" form_tests = r"""
>>> from django.newforms import * >>> from django.newforms import *
>>> import datetime >>> import datetime
>>> import time
>>> import re >>> import re
########### ###########
@ -2600,6 +2601,27 @@ underscores converted to spaces, and the initial letter capitalized.
<li>Password1: <input type="password" name="password1" /></li> <li>Password1: <input type="password" name="password1" /></li>
<li>Password (again): <input type="password" name="password2" /></li> <li>Password (again): <input type="password" name="password2" /></li>
Labels for as_* methods will only end in a colon if they don't end in other
punctuation already.
>>> class Questions(Form):
... q1 = CharField(label='The first question')
... q2 = CharField(label='What is your name?')
... q3 = CharField(label='The answer to life is:')
... q4 = CharField(label='Answer this question!')
... q5 = CharField(label='The last question. Period.')
>>> print Questions(auto_id=False).as_p()
<p>The first question: <input type="text" name="q1" /></p>
<p>What is your name? <input type="text" name="q2" /></p>
<p>The answer to life is: <input type="text" name="q3" /></p>
<p>Answer this question! <input type="text" name="q4" /></p>
<p>The last question. Period. <input type="text" name="q5" /></p>
>>> print Questions().as_p()
<p><label for="id_q1">The first question:</label> <input type="text" name="q1" id="id_q1" /></p>
<p><label for="id_q2">What is your name?</label> <input type="text" name="q2" id="id_q2" /></p>
<p><label for="id_q3">The answer to life is:</label> <input type="text" name="q3" id="id_q3" /></p>
<p><label for="id_q4">Answer this question!</label> <input type="text" name="q4" id="id_q4" /></p>
<p><label for="id_q5">The last question. Period.</label> <input type="text" name="q5" id="id_q5" /></p>
A label can be a Unicode object or a bytestring with special characters. A label can be a Unicode object or a bytestring with special characters.
>>> class UserRegistration(Form): >>> class UserRegistration(Form):
... username = CharField(max_length=10, label='ŠĐĆŽćžšđ') ... username = CharField(max_length=10, label='ŠĐĆŽćžšđ')
@ -3297,6 +3319,94 @@ True
<option value="2016">2016</option> <option value="2016">2016</option>
</select> </select>
# MultiWidget and MultiValueField #############################################
# MultiWidgets are widgets composed of other widgets. They are usually
# combined with MultiValueFields - a field that is composed of other fields.
# MulitWidgets can themselved be composed of other MultiWidgets.
# SplitDateTimeWidget is one example of a MultiWidget.
>>> class ComplexMultiWidget(MultiWidget):
... def __init__(self, attrs=None):
... widgets = (
... TextInput(),
... SelectMultiple(choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))),
... SplitDateTimeWidget(),
... )
... super(ComplexMultiWidget, self).__init__(widgets, attrs)
...
... def decompress(self, value):
... if value:
... data = value.split(',')
... return [data[0], data[1], datetime.datetime(*time.strptime(data[2], "%Y-%m-%d %H:%M:%S")[0:6])]
... return [None, None, None]
... def format_output(self, rendered_widgets):
... return u'\n'.join(rendered_widgets)
>>> w = ComplexMultiWidget()
>>> print w.render('name', 'some text,JP,2007-04-25 06:24:00')
<input type="text" name="name_0" value="some text" />
<select multiple="multiple" name="name_1">
<option value="J" selected="selected">John</option>
<option value="P" selected="selected">Paul</option>
<option value="G">George</option>
<option value="R">Ringo</option>
</select>
<input type="text" name="name_2_0" value="2007-04-25" /><input type="text" name="name_2_1" value="06:24:00" />
>>> class ComplexField(MultiValueField):
... def __init__(self, required=True, widget=None, label=None, initial=None):
... fields = (
... CharField(),
... MultipleChoiceField(choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))),
... SplitDateTimeField()
... )
... super(ComplexField, self).__init__(fields, required, widget, label, initial)
...
... def compress(self, data_list):
... if data_list:
... return '%s,%s,%s' % (data_list[0],''.join(data_list[1]),data_list[2])
... return None
>>> f = ComplexField(widget=w)
>>> f.clean(['some text', ['J','P'], ['2007-04-25','6:24:00']])
u'some text,JP,2007-04-25 06:24:00'
>>> f.clean(['some text',['X'], ['2007-04-25','6:24:00']])
Traceback (most recent call last):
...
ValidationError: [u'Select a valid choice. X is not one of the available choices.']
# If insufficient data is provided, None is substituted
>>> f.clean(['some text',['JP']])
Traceback (most recent call last):
...
ValidationError: [u'This field is required.']
>>> class ComplexFieldForm(Form):
... field1 = ComplexField(widget=w)
>>> f = ComplexFieldForm()
>>> print f
<tr><th><label for="id_field1_0">Field1:</label></th><td><input type="text" name="field1_0" id="id_field1_0" />
<select multiple="multiple" name="field1_1" id="id_field1_1">
<option value="J">John</option>
<option value="P">Paul</option>
<option value="G">George</option>
<option value="R">Ringo</option>
</select>
<input type="text" name="field1_2_0" id="id_field1_2_0" /><input type="text" name="field1_2_1" id="id_field1_2_1" /></td></tr>
>>> f = ComplexFieldForm({'field1_0':'some text','field1_1':['J','P'], 'field1_2_0':'2007-04-25', 'field1_2_1':'06:24:00'})
>>> print f
<tr><th><label for="id_field1_0">Field1:</label></th><td><input type="text" name="field1_0" value="some text" id="id_field1_0" />
<select multiple="multiple" name="field1_1" id="id_field1_1">
<option value="J" selected="selected">John</option>
<option value="P" selected="selected">Paul</option>
<option value="G">George</option>
<option value="R">Ringo</option>
</select>
<input type="text" name="field1_2_0" value="2007-04-25" id="id_field1_2_0" /><input type="text" name="field1_2_1" value="06:24:00" id="id_field1_2_1" /></td></tr>
>>> f.clean_data
{'field1': u'some text,JP,2007-04-25 06:24:00'}
################################# #################################
# Tests of underlying functions # # Tests of underlying functions #
################################# #################################

View File

@ -34,6 +34,9 @@ AttributeError: This QueryDict instance is immutable
>>> q.has_key('foo') >>> q.has_key('foo')
False False
>>> 'foo' in q
False
>>> q.items() >>> q.items()
[] []
@ -124,6 +127,9 @@ MultiValueDictKeyError: "Key 'foo' not found in <MultiValueDict: {}>"
>>> q.has_key('foo') >>> q.has_key('foo')
True True
>>> 'foo' in q
True
>>> q.items() >>> q.items()
[('foo', 'another'), ('name', 'john')] [('foo', 'another'), ('name', 'john')]
@ -218,9 +224,15 @@ AttributeError: This QueryDict instance is immutable
>>> q.has_key('foo') >>> q.has_key('foo')
True True
>>> 'foo' in q
True
>>> q.has_key('bar') >>> q.has_key('bar')
False False
>>> 'bar' in q
False
>>> q.items() >>> q.items()
[('foo', 'bar')] [('foo', 'bar')]
@ -303,9 +315,15 @@ AttributeError: This QueryDict instance is immutable
>>> q.has_key('vote') >>> q.has_key('vote')
True True
>>> 'vote' in q
True
>>> q.has_key('foo') >>> q.has_key('foo')
False False
>>> 'foo' in q
False
>>> q.items() >>> q.items()
[('vote', 'no')] [('vote', 'no')]

View File

@ -133,6 +133,18 @@ class Templates(unittest.TestCase):
# Fail silently when accessing a non-simple method # Fail silently when accessing a non-simple method
'basic-syntax20': ("{{ var.method2 }}", {"var": SomeClass()}, ("","INVALID")), 'basic-syntax20': ("{{ var.method2 }}", {"var": SomeClass()}, ("","INVALID")),
# Don't get confused when parsing something that is almost, but not
# quite, a template tag.
'basic-syntax21': ("a {{ moo %} b", {}, "a {{ moo %} b"),
'basic-syntax22': ("{{ moo #}", {}, "{{ moo #}"),
# Will try to treat "moo #} {{ cow" as the variable. Not ideal, but
# costly to work around, so this triggers an error.
'basic-syntax23': ("{{ moo #} {{ cow }}", {"cow": "cow"}, template.TemplateSyntaxError),
# Embedded newlines make it not-a-tag.
'basic-syntax24': ("{{ moo\n }}", {}, "{{ moo\n }}"),
# List-index syntax allows a template to access a certain item of a subscriptable object. # List-index syntax allows a template to access a certain item of a subscriptable object.
'list-index01': ("{{ var.1 }}", {"var": ["first item", "second item"]}, "second item"), 'list-index01': ("{{ var.1 }}", {"var": ["first item", "second item"]}, "second item"),
@ -157,60 +169,61 @@ class Templates(unittest.TestCase):
'list-index07': ("{{ var.1 }}", {"var": {'1': "hello", 1: "world"}}, "hello"), 'list-index07': ("{{ var.1 }}", {"var": {'1': "hello", 1: "world"}}, "hello"),
# Basic filter usage # Basic filter usage
'basic-syntax21': ("{{ var|upper }}", {"var": "Django is the greatest!"}, "DJANGO IS THE GREATEST!"), 'filter-syntax01': ("{{ var|upper }}", {"var": "Django is the greatest!"}, "DJANGO IS THE GREATEST!"),
# Chained filters # Chained filters
'basic-syntax22': ("{{ var|upper|lower }}", {"var": "Django is the greatest!"}, "django is the greatest!"), 'filter-syntax02': ("{{ var|upper|lower }}", {"var": "Django is the greatest!"}, "django is the greatest!"),
# Raise TemplateSyntaxError for space between a variable and filter pipe # Raise TemplateSyntaxError for space between a variable and filter pipe
'basic-syntax23': ("{{ var |upper }}", {}, template.TemplateSyntaxError), 'filter-syntax03': ("{{ var |upper }}", {}, template.TemplateSyntaxError),
# Raise TemplateSyntaxError for space after a filter pipe # Raise TemplateSyntaxError for space after a filter pipe
'basic-syntax24': ("{{ var| upper }}", {}, template.TemplateSyntaxError), 'filter-syntax04': ("{{ var| upper }}", {}, template.TemplateSyntaxError),
# Raise TemplateSyntaxError for a nonexistent filter # Raise TemplateSyntaxError for a nonexistent filter
'basic-syntax25': ("{{ var|does_not_exist }}", {}, template.TemplateSyntaxError), 'filter-syntax05': ("{{ var|does_not_exist }}", {}, template.TemplateSyntaxError),
# Raise TemplateSyntaxError when trying to access a filter containing an illegal character # Raise TemplateSyntaxError when trying to access a filter containing an illegal character
'basic-syntax26': ("{{ var|fil(ter) }}", {}, template.TemplateSyntaxError), 'filter-syntax06': ("{{ var|fil(ter) }}", {}, template.TemplateSyntaxError),
# Raise TemplateSyntaxError for invalid block tags # Raise TemplateSyntaxError for invalid block tags
'basic-syntax27': ("{% nothing_to_see_here %}", {}, template.TemplateSyntaxError), 'filter-syntax07': ("{% nothing_to_see_here %}", {}, template.TemplateSyntaxError),
# Raise TemplateSyntaxError for empty block tags # Raise TemplateSyntaxError for empty block tags
'basic-syntax28': ("{% %}", {}, template.TemplateSyntaxError), 'filter-syntax08': ("{% %}", {}, template.TemplateSyntaxError),
# Chained filters, with an argument to the first one # Chained filters, with an argument to the first one
'basic-syntax29': ('{{ var|removetags:"b i"|upper|lower }}', {"var": "<b><i>Yes</i></b>"}, "yes"), 'filter-syntax09': ('{{ var|removetags:"b i"|upper|lower }}', {"var": "<b><i>Yes</i></b>"}, "yes"),
# Escaped string as argument # Escaped string as argument
'basic-syntax30': (r'{{ var|default_if_none:" endquote\" hah" }}', {"var": None}, ' endquote" hah'), 'filter-syntax10': (r'{{ var|default_if_none:" endquote\" hah" }}', {"var": None}, ' endquote" hah'),
# Variable as argument # Variable as argument
'basic-syntax31': (r'{{ var|default_if_none:var2 }}', {"var": None, "var2": "happy"}, 'happy'), 'filter-syntax11': (r'{{ var|default_if_none:var2 }}', {"var": None, "var2": "happy"}, 'happy'),
# Default argument testing # Default argument testing
'basic-syntax32': (r'{{ var|yesno:"yup,nup,mup" }} {{ var|yesno }}', {"var": True}, 'yup yes'), 'filter-syntax12': (r'{{ var|yesno:"yup,nup,mup" }} {{ var|yesno }}', {"var": True}, 'yup yes'),
# Fail silently for methods that raise an exception with a "silent_variable_failure" attribute # Fail silently for methods that raise an exception with a
'basic-syntax33': (r'1{{ var.method3 }}2', {"var": SomeClass()}, ("12", "1INVALID2")), # "silent_variable_failure" attribute
'filter-syntax13': (r'1{{ var.method3 }}2', {"var": SomeClass()}, ("12", "1INVALID2")),
# In methods that raise an exception without a "silent_variable_attribute" set to True, # In methods that raise an exception without a
# the exception propagates # "silent_variable_attribute" set to True, the exception propagates
'basic-syntax34': (r'1{{ var.method4 }}2', {"var": SomeClass()}, SomeOtherException), 'filter-syntax14': (r'1{{ var.method4 }}2', {"var": SomeClass()}, SomeOtherException),
# Escaped backslash in argument # Escaped backslash in argument
'basic-syntax35': (r'{{ var|default_if_none:"foo\bar" }}', {"var": None}, r'foo\bar'), 'filter-syntax15': (r'{{ var|default_if_none:"foo\bar" }}', {"var": None}, r'foo\bar'),
# Escaped backslash using known escape char # Escaped backslash using known escape char
'basic-syntax35': (r'{{ var|default_if_none:"foo\now" }}', {"var": None}, r'foo\now'), 'filter-syntax16': (r'{{ var|default_if_none:"foo\now" }}', {"var": None}, r'foo\now'),
# Empty strings can be passed as arguments to filters # Empty strings can be passed as arguments to filters
'basic-syntax36': (r'{{ var|join:"" }}', {'var': ['a', 'b', 'c']}, 'abc'), 'filter-syntax17': (r'{{ var|join:"" }}', {'var': ['a', 'b', 'c']}, 'abc'),
# Make sure that any unicode strings are converted to bytestrings # Make sure that any unicode strings are converted to bytestrings
# in the final output. # in the final output.
'basic-syntax37': (r'{{ var }}', {'var': UnicodeInStrClass()}, '\xc5\xa0\xc4\x90\xc4\x86\xc5\xbd\xc4\x87\xc5\xbe\xc5\xa1\xc4\x91'), 'filter-syntax18': (r'{{ var }}', {'var': UnicodeInStrClass()}, '\xc5\xa0\xc4\x90\xc4\x86\xc5\xbd\xc4\x87\xc5\xbe\xc5\xa1\xc4\x91'),
### COMMENT SYNTAX ######################################################## ### COMMENT SYNTAX ########################################################
'comment-syntax01': ("{# this is hidden #}hello", {}, "hello"), 'comment-syntax01': ("{# this is hidden #}hello", {}, "hello"),