1
0
mirror of https://github.com/django/django.git synced 2025-07-04 17:59:13 +00:00

per-object-permissions: Merged to trunk [4095]

git-svn-id: http://code.djangoproject.com/svn/django/branches/per-object-permissions@4096 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Adrian Holovaty 2006-11-24 04:17:58 +00:00
parent 47fca880e3
commit 1b54fc3aba
87 changed files with 3022 additions and 637 deletions

View File

@ -51,6 +51,7 @@ answer newbie questions, and generally made Django that much better:
Jiri Barton
Ned Batchelder <http://www.nedbatchelder.com/>
Shannon -jj Behrens <http://jjinux.blogspot.com/>
Esdras Beleza <linux@esdrasbeleza.com>
James Bennett
Paul Bissex <http://e-scribe.com/>
Simon Blanchard
@ -91,6 +92,7 @@ answer newbie questions, and generally made Django that much better:
Kieran Holland <http://www.kieranholland.com>
Robert Rock Howard <http://djangomojo.com/>
Jason Huggins <http://www.jrandolph.com/blog/>
Baurzhan Ismagulov <ibr@radix50.net>
jcrasta@gmail.com
Michael Josephson <http://www.sdjournal.com/>
jpellerin@gmail.com
@ -112,6 +114,7 @@ answer newbie questions, and generally made Django that much better:
limodou
mattmcc
Martin Maney <http://www.chipy.org/Martin_Maney>
masonsimon+django@gmail.com
Manuzhai
Petar Marić
mark@junklight.com
@ -159,6 +162,7 @@ answer newbie questions, and generally made Django that much better:
Amit Upadhyay
Geert Vanderkelen
Milton Waddams
wam-djangobug@wamber.net
Dan Watson <http://theidioteque.net/>
Rachel Willmer <http://www.willmer.com/kb/>
Gary Wilson <gary.wilson@gmail.com>

View File

@ -77,7 +77,7 @@ class Settings(object):
self.SETTINGS_MODULE = settings_module
try:
mod = __import__(self.SETTINGS_MODULE, '', '', [''])
mod = __import__(self.SETTINGS_MODULE, {}, {}, [''])
except ImportError, e:
raise EnvironmentError, "Could not import settings '%s' (Is it on sys.path? Does it have syntax errors?): %s" % (self.SETTINGS_MODULE, e)
@ -97,7 +97,7 @@ class Settings(object):
new_installed_apps = []
for app in self.INSTALLED_APPS:
if app.endswith('.*'):
appdir = os.path.dirname(__import__(app[:-2], '', '', ['']).__file__)
appdir = os.path.dirname(__import__(app[:-2], {}, {}, ['']).__file__)
for d in os.listdir(appdir):
if d.isalpha() and os.path.isdir(os.path.join(appdir, d)):
new_installed_apps.append('%s.%s' % (app[:-2], d))

View File

@ -101,6 +101,7 @@ DATABASE_USER = '' # Not used with sqlite3.
DATABASE_PASSWORD = '' # Not used with sqlite3.
DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3.
DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3.
DATABASE_OPTIONS = {} # Set to empty dictionary for default.
# Host for sending e-mail.
EMAIL_HOST = 'localhost'
@ -228,6 +229,10 @@ MONTH_DAY_FORMAT = 'F j'
# Hint: you really don't!
TRANSACTIONS_MANAGED = False
# The User-Agent string to use when checking for URL validity through the
# isExistingURL validator.
URL_VALIDATOR_USER_AGENT = "Django/0.96pre (http://www.djangoproject.com)"
##############
# MIDDLEWARE #
##############

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Django 1.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2006-09-25 16:04+0200\n"
"POT-Creation-Date: 2006-11-15 18:35+0100\n"
"PO-Revision-Date: 2005-10-08 00:03+0200\n"
"Last-Translator: Georg Bauer <gb@bofh.ms>\n"
"MIME-Version: 1.0\n"
@ -452,7 +452,7 @@ msgid ""
"Looks like your browser isn't configured to accept cookies. Please enable "
"cookies, reload this page, and try again."
msgstr ""
"Es sieht danach aus, das der Browser keine Cookies akzeptiert. Bitte im "
"Es sieht danach aus, dass der Browser keine Cookies akzeptiert. Bitte im "
"Browser Cookies aktivieren und diese Seite neu laden."
#: contrib/admin/views/decorators.py:83
@ -470,13 +470,13 @@ msgstr ""
msgid "Site administration"
msgstr "Website Verwaltung"
#: contrib/admin/views/main.py:257 contrib/admin/views/auth.py:17
#: contrib/admin/views/main.py:257 contrib/admin/views/auth.py:18
#, python-format
msgid "The %(name)s \"%(obj)s\" was added successfully."
msgstr "%(name)s \"%(obj)s\" wurde erfolgreich hinzugefügt."
#: contrib/admin/views/main.py:261 contrib/admin/views/main.py:347
#: contrib/admin/views/auth.py:22
#: contrib/admin/views/auth.py:23
msgid "You may edit it again below."
msgstr "Das Element kann jetzt weiter geändert werden."
@ -496,7 +496,7 @@ msgid "Added %s."
msgstr "%s hinzugefügt."
#: contrib/admin/views/main.py:335 contrib/admin/views/main.py:337
#: contrib/admin/views/main.py:339
#: contrib/admin/views/main.py:339 db/models/manipulators.py:306
msgid "and"
msgstr "und"
@ -702,7 +702,7 @@ msgstr "XML Text"
msgid "%s does not appear to be a urlpattern object"
msgstr "%s ist scheinbar kein urlpattern Objekt"
#: contrib/admin/views/auth.py:28
#: contrib/admin/views/auth.py:29
msgid "Add user"
msgstr "Benutzer zufügen"
@ -861,10 +861,6 @@ msgstr "Keine vorhanden"
msgid "Add %(name)s"
msgstr "%(name)s zufügen"
#: contrib/admin/templates/admin/login.html:22
msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?"
msgstr "Haben Sie <a href=\"/password_reset/\">ihr Passwort vergessen</a>?"
#: contrib/admin/templates/admin/base.html:25
msgid "Welcome,"
msgstr "Willkommen,"
@ -891,7 +887,7 @@ msgid ""
"Are you sure you want to delete the %(object_name)s \"%(escaped_object)s\"? "
"All of the following related items will be deleted:"
msgstr ""
"Sind Sie sicher, das Sie %(object_name)s \"%(escaped_object)s\" löschen "
"Sind Sie sicher, dass Sie %(object_name)s \"%(escaped_object)s\" löschen "
"wollen? Es werden zusätzlich die folgenden abhängigen Daten mit gelöscht:"
#: contrib/admin/templates/admin/delete_confirmation.html:26
@ -1061,7 +1057,7 @@ msgid ""
"password twice so we can verify you typed it in correctly."
msgstr ""
"Bitte geben Sie aus Sicherheitsgründen erst Ihr altes Kennwort und darunter "
"dann zweimal (um sicherzustellen, das Sie es korrekt eingegeben haben) das "
"dann zweimal (um sicherzustellen, dass Sie es korrekt eingegeben haben) das "
"neue Kennwort ein."
#: contrib/admin/templates/registration/password_change_form.html:17
@ -1087,7 +1083,7 @@ msgstr "Sie erhalten diese Mail, weil Sie ein neues Kennwort"
#: contrib/admin/templates/registration/password_reset_email.html:3
#, python-format
msgid "for your user account at %(site_name)s"
msgstr "für ihren Benutzer bei %(site_name)s angefordert haben."
msgstr "für Ihren Benutzer bei %(site_name)s angefordert haben."
#: contrib/admin/templates/registration/password_reset_email.html:5
#, python-format
@ -1104,7 +1100,7 @@ msgstr "Ihr Benutzername, falls Sie ihn vergessen haben:"
#: contrib/admin/templates/registration/password_reset_email.html:13
msgid "Thanks for using our site!"
msgstr "Vielen Dank, das Sie unsere Seiten benutzen!"
msgstr "Vielen Dank, dass Sie unsere Seiten benutzen!"
#: contrib/admin/templates/registration/password_reset_email.html:15
#, python-format
@ -1367,7 +1363,7 @@ msgid ""
"Designates that this user has all permissions without explicitly assigning "
"them."
msgstr ""
"Bestimmt, das dieser Benutzer alle Berechtigungen hat, ohne diese einzeln "
"Bestimmt, dass dieser Benutzer alle Berechtigungen hat, ohne diese einzeln "
"zuweisen zu müssen."
#: contrib/auth/models.py:98
@ -1414,10 +1410,18 @@ msgstr "Wichtige Daten"
msgid "Groups"
msgstr "Gruppen"
#: contrib/auth/models.py:256
#: contrib/auth/models.py:258
msgid "message"
msgstr "Mitteilung"
#: contrib/auth/forms.py:16
msgid "The two password fields didn't match."
msgstr "Die zwei Passwörter sind nicht gleich."
#: contrib/auth/forms.py:24
msgid "A user with that username already exists."
msgstr "Ein Benutzer mit diesem Namen existiert bereits."
#: contrib/auth/forms.py:52
msgid ""
"Your Web browser doesn't appear to have cookies enabled. Cookies are "
@ -1432,10 +1436,10 @@ msgstr "Dieser Benutzer ist inaktiv."
#: contrib/auth/forms.py:84
msgid ""
"That e-mail address doesn't have an associated user acount. Are you sure "
"That e-mail address doesn't have an associated user account. Are you sure "
"you've registered?"
msgstr ""
"Die Email-Adresse hat keinen Benutzer zugeordnet. Sicher, das die Adresse "
"Die Email-Adresse hat keinen Benutzer zugeordnet. Sicher, dass die Adresse "
"hier angemeldet ist?"
#: contrib/auth/forms.py:116
@ -1783,58 +1787,62 @@ msgid "Norwegian"
msgstr "Norwegisch"
#: conf/global_settings.py:59
msgid "Polish"
msgstr "Polnisch"
#: conf/global_settings.py:60
msgid "Brazilian"
msgstr "Brasilianisch"
#: conf/global_settings.py:60
#: conf/global_settings.py:61
msgid "Romanian"
msgstr "Rumänisch"
#: conf/global_settings.py:61
#: conf/global_settings.py:62
msgid "Russian"
msgstr "Russisch"
#: conf/global_settings.py:62
#: conf/global_settings.py:63
msgid "Slovak"
msgstr "Slowakisch"
#: conf/global_settings.py:63
#: conf/global_settings.py:64
msgid "Slovenian"
msgstr "Slowenisch"
#: conf/global_settings.py:64
#: conf/global_settings.py:65
msgid "Serbian"
msgstr "Serbisch"
#: conf/global_settings.py:65
#: conf/global_settings.py:66
msgid "Swedish"
msgstr "Schwedisch"
#: conf/global_settings.py:66
#: conf/global_settings.py:67
msgid "Tamil"
msgstr "Tamilisch"
#: conf/global_settings.py:67
#: conf/global_settings.py:68
msgid "Turkish"
msgstr "Türkisch"
#: conf/global_settings.py:68
#: conf/global_settings.py:69
msgid "Ukrainian"
msgstr "Ukrainisch"
#: conf/global_settings.py:69
#: conf/global_settings.py:70
msgid "Simplified Chinese"
msgstr "Vereinfachtes Chinesisch"
#: conf/global_settings.py:70
#: conf/global_settings.py:71
msgid "Traditional Chinese"
msgstr "Traditionelles Chinesisch"
#: core/validators.py:63
#: core/validators.py:64
msgid "This value must contain only letters, numbers and underscores."
msgstr "Dieser Wert darf nur Buchstaben, Ziffern und Unterstriche enthalten."
#: core/validators.py:67
#: core/validators.py:68
msgid ""
"This value must contain only letters, numbers, underscores, dashes or "
"slashes."
@ -1842,85 +1850,85 @@ msgstr ""
"Dieser Wert darf nur Buchstaben, Ziffern, Unterstriche und Schrägstriche "
"enthalten."
#: core/validators.py:71
#: core/validators.py:72
msgid "This value must contain only letters, numbers, underscores or hyphens."
msgstr ""
"Dieser Wert darf nur Buchstaben, Ziffern, Unterstriche und Bindestriche "
"enthalten."
#: core/validators.py:75
#: core/validators.py:76
msgid "Uppercase letters are not allowed here."
msgstr "Großbuchstaben sind hier nicht erlaubt."
#: core/validators.py:79
#: core/validators.py:80
msgid "Lowercase letters are not allowed here."
msgstr "Kleinbuchstaben sind hier nicht erlaubt."
#: core/validators.py:86
#: core/validators.py:87
msgid "Enter only digits separated by commas."
msgstr "Hier sind nur durch Komma getrennte Ziffern erlaubt."
#: core/validators.py:98
#: core/validators.py:99
msgid "Enter valid e-mail addresses separated by commas."
msgstr "Bitte mit Komma getrennte, gültige eMail-Adressen eingeben."
#: core/validators.py:102
#: core/validators.py:103
msgid "Please enter a valid IP address."
msgstr "Bitte eine gültige IP-Adresse eingeben."
#: core/validators.py:106
#: core/validators.py:107
msgid "Empty values are not allowed here."
msgstr "Dieses Feld darf nicht leer sein."
#: core/validators.py:110
#: core/validators.py:111
msgid "Non-numeric characters aren't allowed here."
msgstr "Nichtnumerische Zeichen sind hier nicht erlaubt."
#: core/validators.py:114
#: core/validators.py:115
msgid "This value can't be comprised solely of digits."
msgstr "Dieser Wert darf nicht nur aus Ziffern bestehen."
#: core/validators.py:119
#: core/validators.py:120
msgid "Enter a whole number."
msgstr "Bitte eine ganze Zahl eingeben."
#: core/validators.py:123
#: core/validators.py:124
msgid "Only alphabetical characters are allowed here."
msgstr "Nur alphabetische Zeichen sind hier erlaubt."
#: core/validators.py:138
#: core/validators.py:139
msgid "Year must be 1900 or later."
msgstr "Das Jahr muss 1900 oder später sein."
#: core/validators.py:142
#: core/validators.py:143
#, python-format
msgid "Invalid date: %s."
msgstr "Ungültiges Datum: %s"
#: core/validators.py:146 db/models/fields/__init__.py:415
#: core/validators.py:147 db/models/fields/__init__.py:424
msgid "Enter a valid date in YYYY-MM-DD format."
msgstr "Bitte ein gültiges Datum im Format JJJJ-MM-TT eingeben."
#: core/validators.py:151
#: core/validators.py:152
msgid "Enter a valid time in HH:MM format."
msgstr "Bitte eine gültige Zeit im Format SS:MM eingeben."
#: core/validators.py:155 db/models/fields/__init__.py:477
#: core/validators.py:156 db/models/fields/__init__.py:488
msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format."
msgstr ""
"Bitte eine gültige Datums- und Zeitangabe im Format JJJJ-MM-TT SS:MM "
"eingeben."
#: core/validators.py:160
#: core/validators.py:161
msgid "Enter a valid e-mail address."
msgstr "Bitte eine gültige eMail-Adresse eingeben"
#: core/validators.py:172 core/validators.py:401 forms/__init__.py:661
#: core/validators.py:173 core/validators.py:442 forms/__init__.py:667
msgid "No file was submitted. Check the encoding type on the form."
msgstr ""
"Es wurde keine Datei geschickt. Eventuell ist das Formular-Encoding falsch."
#: core/validators.py:176
#: core/validators.py:177
msgid ""
"Upload a valid image. The file you uploaded was either not an image or a "
"corrupted image."
@ -1928,27 +1936,27 @@ msgstr ""
"Bitte ein Bild hochladen. Die Datei, die hochgeladen wurde, ist kein Bild "
"oder ist defekt."
#: core/validators.py:183
#: core/validators.py:184
#, python-format
msgid "The URL %s does not point to a valid image."
msgstr "Die URL %s zeigt nicht auf ein gültiges Bild."
#: core/validators.py:187
#: core/validators.py:188
#, python-format
msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid."
msgstr ""
"Telefonnummern müssen im Format XXX-XXX-XXXX sein. \"%s\" ist ungültig."
#: core/validators.py:195
#: core/validators.py:196
#, python-format
msgid "The URL %s does not point to a valid QuickTime video."
msgstr "Die URL %s zeigt nicht auf ein gültiges QuickTime video."
#: core/validators.py:199
#: core/validators.py:200
msgid "A valid URL is required."
msgstr "Eine gültige URL ist hier verlangt."
#: core/validators.py:213
#: core/validators.py:214
#, python-format
msgid ""
"Valid HTML is required. Specific errors are:\n"
@ -1957,71 +1965,83 @@ msgstr ""
"Bitte gültiges HTML eingeben. Fehler sind:\n"
"%s"
#: core/validators.py:220
#: core/validators.py:221
#, python-format
msgid "Badly formed XML: %s"
msgstr "Ungültiges XML: %s"
#: core/validators.py:230
#: core/validators.py:238
#, python-format
msgid "Invalid URL: %s"
msgstr "Ungültige URL: %s"
#: core/validators.py:234 core/validators.py:236
#: core/validators.py:243 core/validators.py:245
#, python-format
msgid "The URL %s is a broken link."
msgstr "Die URL %s funktioniert nicht."
#: core/validators.py:242
#: core/validators.py:251
msgid "Enter a valid U.S. state abbreviation."
msgstr "Bitte eine gültige Abkürzung für einen US-Staat eingeben."
#: core/validators.py:256
#: core/validators.py:265
#, python-format
msgid "Watch your mouth! The word %s is not allowed here."
msgid_plural "Watch your mouth! The words %s are not allowed here."
msgstr[0] "Keine Schimpfworte! Das Wort %s ist hier nicht gern gesehen!"
msgstr[1] "Keine Schimpfworte! Die Wörter %s sind hier nicht gern gesehen!"
#: core/validators.py:263
#: core/validators.py:272
#, python-format
msgid "This field must match the '%s' field."
msgstr "Dieses Feld muss zum Feld '%s' passen."
#: core/validators.py:282
#: core/validators.py:291
msgid "Please enter something for at least one field."
msgstr "Bitte mindestens eines der Felder ausfüllen."
#: core/validators.py:291 core/validators.py:302
#: core/validators.py:300 core/validators.py:311
msgid "Please enter both fields or leave them both empty."
msgstr "Bitte entweder beide Felder ausfüllen, oder beide leer lassen."
#: core/validators.py:309
#: core/validators.py:318
#, python-format
msgid "This field must be given if %(field)s is %(value)s"
msgstr ""
"Dieses Feld muss gefüllt sein, wenn Feld %(field)s den Wert %(value)s hat."
#: core/validators.py:321
#: core/validators.py:330
#, python-format
msgid "This field must be given if %(field)s is not %(value)s"
msgstr ""
"Dieses Feld muss gefüllt sein, wenn Feld %(field)s nicht %(value)s ist."
#: core/validators.py:340
#: core/validators.py:349
msgid "Duplicate values are not allowed."
msgstr "Doppelte Werte sind hier nicht erlaubt."
#: core/validators.py:363
#: core/validators.py:364
msgid "This value must be between %s and %s."
msgstr "Dieser Wert muss zwischen %s und %s sein."
#: core/validators.py:366
msgid "This value must be at least %s."
msgstr "Dieser Wert muss mindestens %s sein."
#: core/validators.py:368
msgid "This value must be no more than %s."
msgstr "Dieser Wert darf maximal %s sein."
#: core/validators.py:404
#, python-format
msgid "This value must be a power of %s."
msgstr "Dieser Wert muss eine Potenz von %s sein."
#: core/validators.py:374
#: core/validators.py:415
msgid "Please enter a valid decimal number."
msgstr "Bitte eine gültige Dezimalzahl eingeben."
#: core/validators.py:378
#: core/validators.py:419
#, python-format
msgid "Please enter a valid decimal number with at most %s total digit."
msgid_plural ""
@ -2029,7 +2049,7 @@ msgid_plural ""
msgstr[0] "Bitte eine gültige Dezimalzahl mit maximal %s Ziffer eingeben."
msgstr[1] "Bitte eine gültige Dezimalzahl mit maximal %s Ziffern eingeben."
#: core/validators.py:381
#: core/validators.py:422
#, python-format
msgid ""
"Please enter a valid decimal number with a whole part of at most %s digit."
@ -2038,7 +2058,7 @@ msgid_plural ""
msgstr[0] "Bitte eine gültige Dezimalzahl mit maximal %s Ziffer eingeben."
msgstr[1] "Bitte eine gültige Dezimalzahl mit maximal %s Ziffern eingeben."
#: core/validators.py:384
#: core/validators.py:425
#, python-format
msgid "Please enter a valid decimal number with at most %s decimal place."
msgid_plural ""
@ -2048,39 +2068,39 @@ msgstr[0] ""
msgstr[1] ""
"Bitte eine gültige Dezimalzahl mit maximal %s Dezimalstellen eingeben."
#: core/validators.py:394
#: core/validators.py:435
#, python-format
msgid "Make sure your uploaded file is at least %s bytes big."
msgstr ""
"Bitte sicherstellen, daß die hochgeladene Datei mindestens %s Bytes gross "
"ist."
#: core/validators.py:395
#: core/validators.py:436
#, python-format
msgid "Make sure your uploaded file is at most %s bytes big."
msgstr ""
"Bitte sicherstellen, daß die hochgeladene Datei maximal %s Bytes gross ist."
#: core/validators.py:412
#: core/validators.py:453
msgid "The format for this field is wrong."
msgstr "Das Format für dieses Feld ist falsch."
#: core/validators.py:427
#: core/validators.py:468
msgid "This field is invalid."
msgstr "Dieses Feld ist ungültig."
#: core/validators.py:463
#: core/validators.py:504
#, python-format
msgid "Could not retrieve anything from %s."
msgstr "Konnte nichts von %s empfangen."
#: core/validators.py:466
#: core/validators.py:507
#, python-format
msgid ""
"The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
msgstr "Die URL %(url)s lieferte den falschen Content-Type '%(contenttype)s'."
#: core/validators.py:499
#: core/validators.py:540
#, python-format
msgid ""
"Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with "
@ -2089,7 +2109,7 @@ msgstr ""
"Bitte das ungeschlossene %(tag)s Tag in Zeile %(line)s schließen. Die Zeile "
"beginnt mit \"%(start)s\"."
#: core/validators.py:503
#: core/validators.py:544
#, python-format
msgid ""
"Some text starting on line %(line)s is not allowed in that context. (Line "
@ -2098,7 +2118,7 @@ msgstr ""
"In Zeile %(line)s ist Text, der nicht in dem Kontext erlaubt ist. Die Zeile "
"beginnt mit \"%(start)s\"."
#: core/validators.py:508
#: core/validators.py:549
#, python-format
msgid ""
"\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%"
@ -2107,7 +2127,7 @@ msgstr ""
"Das Attribute %(attr)s in Zeile %(line)s ist ungültig. Die Zeile beginnt mit "
"\"%(start)s\"."
#: core/validators.py:513
#: core/validators.py:554
#, python-format
msgid ""
"\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%"
@ -2116,7 +2136,7 @@ msgstr ""
"<%(tag)s> in Zeile %(line)s ist ungültig. Die Zeile beginnt mit \"%(start)s"
"\"."
#: core/validators.py:517
#: core/validators.py:558
#, python-format
msgid ""
"A tag on line %(line)s is missing one or more required attributes. (Line "
@ -2125,7 +2145,7 @@ msgstr ""
"Ein Tag in Zeile %(line)s hat eines oder mehrere Pflichtattribute nicht. Die "
"Zeile beginnt mit \"%(start)s\"."
#: core/validators.py:522
#: core/validators.py:563
#, python-format
msgid ""
"The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line "
@ -2149,37 +2169,37 @@ msgstr "%(verbose_name)s wurde erfolgreich aktualisiert."
msgid "The %(verbose_name)s was deleted."
msgstr "%(verbose_name)s wurde gelöscht"
#: db/models/manipulators.py:302
#: db/models/manipulators.py:305
#, python-format
msgid "%(object)s with this %(type)s already exists for the given %(field)s."
msgstr ""
"Ein '%(object)s' in dieser '%(type)s' existiert bereits für dieses '%(field)"
"s'."
#: db/models/fields/__init__.py:40
#: db/models/fields/__init__.py:41
#, python-format
msgid "%(optname)s with this %(fieldname)s already exists."
msgstr "Ein '%(optname)s' mit diesem '%(fieldname)s' existiert bereits."
#: db/models/fields/__init__.py:114 db/models/fields/__init__.py:265
#: db/models/fields/__init__.py:551 db/models/fields/__init__.py:562
#: forms/__init__.py:346
#: db/models/fields/__init__.py:115 db/models/fields/__init__.py:266
#: db/models/fields/__init__.py:569 db/models/fields/__init__.py:580
#: forms/__init__.py:352
msgid "This field is required."
msgstr "Dieses Feld ist zwingend."
#: db/models/fields/__init__.py:340
#: db/models/fields/__init__.py:349
msgid "This value must be an integer."
msgstr "Dieser Wert muss eine Ganzzahl sein."
#: db/models/fields/__init__.py:372
#: db/models/fields/__init__.py:381
msgid "This value must be either True or False."
msgstr "Dieser Wert muss wahr oder falsch sein."
#: db/models/fields/__init__.py:388
#: db/models/fields/__init__.py:397
msgid "This field cannot be null."
msgstr "Dieses Feld darf nicht leer sein."
#: db/models/fields/__init__.py:571
#: db/models/fields/__init__.py:589
msgid "Enter a valid filename."
msgstr "Bitte einen gültigen Dateinamen eingeben"
@ -2209,36 +2229,36 @@ msgstr[0] ""
msgstr[1] ""
"Bitte gültige IDs für %(self)s eingeben. Die Werte %(value)r sind ungültig."
#: forms/__init__.py:381
#: forms/__init__.py:387
#, python-format
msgid "Ensure your text is less than %s character."
msgid_plural "Ensure your text is less than %s characters."
msgstr[0] "Bitte sicherstellen, das der Text weniger als %s Zeichen hat."
msgstr[1] "Bitte sicherstellen, das der Text weniger als %s Zeichen hat."
msgstr[0] "Bitte sicherstellen, dass der Text weniger als %s Zeichen hat."
msgstr[1] "Bitte sicherstellen, dass der Text weniger als %s Zeichen hat."
#: forms/__init__.py:386
#: forms/__init__.py:392
msgid "Line breaks are not allowed here."
msgstr "Zeilenumbrüche sind hier nicht erlaubt."
#: forms/__init__.py:487 forms/__init__.py:560 forms/__init__.py:599
#: forms/__init__.py:493 forms/__init__.py:566 forms/__init__.py:605
#, python-format
msgid "Select a valid choice; '%(data)s' is not in %(choices)s."
msgstr ""
"Bitte eine gültige Auswahl treffen; '%(data)s' ist nicht in %(choices)s."
#: forms/__init__.py:663
#: forms/__init__.py:669
msgid "The submitted file is empty."
msgstr "Die ausgewählte Datei ist leer."
#: forms/__init__.py:719
#: forms/__init__.py:725
msgid "Enter a whole number between -32,768 and 32,767."
msgstr "Bitte eine ganze Zahl zwischen -32.768 und 32.767 eingeben."
#: forms/__init__.py:729
#: forms/__init__.py:735
msgid "Enter a positive number."
msgstr "Bitte eine ganze, positive Zahl eingeben."
#: forms/__init__.py:739
#: forms/__init__.py:745
msgid "Enter a whole number between 0 and 32,767."
msgstr "Bitte eine ganze Zahl zwischen 0 und 32.767 eingeben."

View File

@ -107,6 +107,11 @@ msgid ""
"\n"
"http://%(domain)s%(url)s"
msgstr ""
"Σχόλιο από τον/την %(user)s την %(date)s\n"
"\n"
"%(comment)s\n"
"\n"
"http://%(domain)s%(url)s"
#: contrib/comments/models.py:168
msgid "person's name"
@ -141,11 +146,11 @@ msgstr "ημερομηνία βαθμολογίας"
#: contrib/comments/models.py:237
#, fuzzy
msgid "karma score"
msgstr "βαθμολογία"
msgstr "karma"
#: contrib/comments/models.py:238
msgid "karma scores"
msgstr ""
msgstr "karma"
#: contrib/comments/models.py:242
#, python-format
@ -159,7 +164,7 @@ msgid ""
"\n"
"%(text)s"
msgstr ""
"Αυτο το σχόλιο σημειώθει απο %(χρήστη)ες\n"
"Αυτο το σχόλιο σημειώθηκε απο %(χρήστη)ες\n"
"\n"
"%(κείμενο)α"
@ -245,7 +250,7 @@ msgstr ""
#: contrib/comments/views/comments.py:193
#: contrib/comments/views/comments.py:284
msgid "One or more of the required fields wasn't submitted"
msgstr "Ένα ή περισσότερα από τα απαιτούμενα πεδία δεν υποβλίθει"
msgstr "Ένα ή περισσότερα από τα απαιτούμενα πεδία δεν υπεβλήθει"
#: contrib/comments/views/comments.py:197
#: contrib/comments/views/comments.py:286
@ -268,7 +273,7 @@ msgstr ""
#: contrib/comments/templates/comments/form.html:8
#: contrib/admin/templates/admin/login.html:17
msgid "Username:"
msgstr ""
msgstr "Όνομα χρήστη:"
#: contrib/comments/templates/comments/form.html:6
#: contrib/admin/templates/admin/login.html:20
@ -298,21 +303,21 @@ msgstr "Ξεχάσατε τον κωδικό σας;"
#: contrib/admin/templates/admin_doc/index.html:4
#: contrib/admin/templates/admin_doc/model_index.html:5
msgid "Log out"
msgstr ""
msgstr "Αποσύνδεση"
#: contrib/comments/templates/comments/form.html:12
msgid "Ratings"
msgstr ""
msgstr "Βαθμολογίες"
#: contrib/comments/templates/comments/form.html:12
#: contrib/comments/templates/comments/form.html:23
msgid "Required"
msgstr ""
msgstr "Απαραίτητο"
#: contrib/comments/templates/comments/form.html:12
#: contrib/comments/templates/comments/form.html:23
msgid "Optional"
msgstr ""
msgstr "Προαιρετικό"
#: contrib/comments/templates/comments/form.html:23
msgid "Post a photo"
@ -326,11 +331,11 @@ msgstr "Σχόλιο:"
#: contrib/comments/templates/comments/form.html:32
#: contrib/comments/templates/comments/freeform.html:9
msgid "Preview comment"
msgstr ""
msgstr "Προεπισκόπηση σχολίου"
#: contrib/comments/templates/comments/freeform.html:4
msgid "Your name:"
msgstr ""
msgstr "Το όνομα σας:"
#: contrib/admin/filterspecs.py:40
#, python-format
@ -338,15 +343,17 @@ msgid ""
"<h3>By %s:</h3>\n"
"<ul>\n"
msgstr ""
"<h3>Από %s:</h3>\n"
"<ul>\n"
#: contrib/admin/filterspecs.py:70 contrib/admin/filterspecs.py:88
#: contrib/admin/filterspecs.py:143
msgid "All"
msgstr ""
msgstr "Όλα"
#: contrib/admin/filterspecs.py:109
msgid "Any date"
msgstr ""
msgstr "Όλες οι ημερομηνίες"
#: contrib/admin/filterspecs.py:110
msgid "Today"
@ -354,7 +361,7 @@ msgstr "Σήμερα"
#: contrib/admin/filterspecs.py:113
msgid "Past 7 days"
msgstr ""
msgstr "Τις προηγούμενες 7 ημέρες"
#: contrib/admin/filterspecs.py:115
msgid "This month"
@ -374,7 +381,7 @@ msgstr "Όχι"
#: contrib/admin/filterspecs.py:150
msgid "Unknown"
msgstr "γνωστο"
msgstr "Άγνωστο"
#: contrib/admin/models.py:16
msgid "action time"
@ -441,7 +448,7 @@ msgstr ""
#: contrib/admin/views/decorators.py:82
msgid "Usernames cannot contain the '@' character."
msgstr "Τα ονόματα των Χρηστών δεν μπορόυν να περιέχουν τον χαρακτήρα '@'."
msgstr "Τα ονόματα των χρηστών δεν μπορόυν να περιέχουν τον χαρακτήρα '@'."
#: contrib/admin/views/decorators.py:84
#, python-format
@ -452,16 +459,16 @@ msgstr ""
#: contrib/admin/views/main.py:226
msgid "Site administration"
msgstr "Διαχείριση του Διαδυκτιακού χώρου"
msgstr "Διαχείριση του Διαδικτυακού χώρου"
#: contrib/admin/views/main.py:260
#, python-format
msgid "The %(name)s \"%(obj)s\" was added successfully."
msgstr ""
msgstr "Το %(name)s \"%(obj)s\" αποθηκεύτηκε επιτυχώς."
#: contrib/admin/views/main.py:264 contrib/admin/views/main.py:348
msgid "You may edit it again below."
msgstr ""
msgstr "Μπορείτε να το επεξεργαστείτε ξανα παρακάτω."
#: contrib/admin/views/main.py:272 contrib/admin/views/main.py:357
#, python-format
@ -471,12 +478,12 @@ msgstr "Μπορείτε να προσθέσετε ακόμα ένα %s απο
#: contrib/admin/views/main.py:290
#, python-format
msgid "Add %s"
msgstr ""
msgstr "Προσθήκη %s"
#: contrib/admin/views/main.py:336
#, python-format
msgid "Added %s."
msgstr ""
msgstr "Προστέθηκε %s."
#: contrib/admin/views/main.py:336 contrib/admin/views/main.py:338
#: contrib/admin/views/main.py:340
@ -486,32 +493,33 @@ msgstr "και"
#: contrib/admin/views/main.py:338
#, python-format
msgid "Changed %s."
msgstr ""
msgstr "Επεξεργάσθηκε %s."
#: contrib/admin/views/main.py:340
#, python-format
msgid "Deleted %s."
msgstr ""
msgstr "Διεγράφη %s."
#: contrib/admin/views/main.py:343
msgid "No fields changed."
msgstr ""
msgstr "Κανένα πεδίο δεν άλλαξε."
#: contrib/admin/views/main.py:346
#, python-format
msgid "The %(name)s \"%(obj)s\" was changed successfully."
msgstr ""
msgstr "Το %(name)s \"%(obj)s\" επεξεργάσθηκε επιτυχώς."
#: contrib/admin/views/main.py:354
#, python-format
msgid ""
"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
msgstr ""
"Το %(name)s \"%(obj)s\" αποθηκεύθηκε επιτυχώς. Μπορείτε να το επεξεργαστείτε πάλι παρακάτω."
#: contrib/admin/views/main.py:392
#, python-format
msgid "Change %s"
msgstr ""
msgstr "Αλλαγή %s"
#: contrib/admin/views/main.py:470
#, python-format
@ -535,17 +543,17 @@ msgstr "Είστε σίγουρος;"
#: contrib/admin/views/main.py:533
#, python-format
msgid "Change history: %s"
msgstr ""
msgstr "Ιστορικό Αλλαγών: %s"
#: contrib/admin/views/main.py:565
#, python-format
msgid "Select %s"
msgstr ""
msgstr "Επιλογή %s"
#: contrib/admin/views/main.py:565
#, python-format
msgid "Select %s to change"
msgstr ""
msgstr "Επιλέξτε %s προς αλλαγή"
#: contrib/admin/views/doc.py:277 contrib/admin/views/doc.py:286
#: contrib/admin/views/doc.py:288 contrib/admin/views/doc.py:294
@ -555,7 +563,7 @@ msgstr "Ακέραιος"
#: contrib/admin/views/doc.py:278
msgid "Boolean (Either True or False)"
msgstr "Boolean (Είτε Αλήθεια ή Ψέμα)"
msgstr "Boolean (Είτε Αληθές ή Ψέυδές)"
#: contrib/admin/views/doc.py:279 contrib/admin/views/doc.py:296
#, python-format
@ -580,7 +588,7 @@ msgstr "Ηλεκτρονική διεύθυνση"
#: contrib/admin/views/doc.py:284 contrib/admin/views/doc.py:287
msgid "File path"
msgstr ""
msgstr "Τοποθεσία Αρχείου"
#: contrib/admin/views/doc.py:285
msgid "Decimal number"
@ -592,7 +600,7 @@ msgstr ""
#: contrib/admin/views/doc.py:292
msgid "Relation to parent model"
msgstr ""
msgstr "Σχέση με το γονεϊκό μοντέλο"
#: contrib/admin/views/doc.py:293
msgid "Phone number"
@ -627,7 +635,7 @@ msgstr ""
#: contrib/admin/templates/registration/password_change_form.html:3
#: contrib/admin/templates/admin_doc/bookmarklets.html:3
msgid "Documentation"
msgstr ""
msgstr "Τεκμηρίωση"
#: contrib/admin/templates/admin/object_history.html:3
#: contrib/admin/templates/admin/change_list.html:5
@ -667,11 +675,11 @@ msgstr "Home"
#: contrib/admin/templates/admin/object_history.html:5
#: contrib/admin/templates/admin/change_form.html:20
msgid "History"
msgstr ""
msgstr "Ιστορικό"
#: contrib/admin/templates/admin/object_history.html:18
msgid "Date/time"
msgstr ""
msgstr "Ημερομηνία/Ώρα"
#: contrib/admin/templates/admin/object_history.html:19
msgid "User"
@ -679,7 +687,7 @@ msgstr "Χρήστης"
#: contrib/admin/templates/admin/object_history.html:20
msgid "Action"
msgstr ""
msgstr "Δράση"
#: contrib/admin/templates/admin/object_history.html:26
msgid "DATE_WITH_TIME_FULL"
@ -697,19 +705,19 @@ msgstr "Διαχειριστής ιστοσελίδας Django"
#: contrib/admin/templates/admin/base_site.html:7
msgid "Django administration"
msgstr ""
msgstr "Διαχείριση Django"
#: contrib/admin/templates/admin/500.html:4
msgid "Server error"
msgstr ""
msgstr "Σφάλμα Διακομιστή"
#: contrib/admin/templates/admin/500.html:6
msgid "Server error (500)"
msgstr ""
msgstr "Σφάλμα Διακομιστή (500)"
#: contrib/admin/templates/admin/500.html:9
msgid "Server Error <em>(500)</em>"
msgstr ""
msgstr "Σφάλμα Διακομιστή <em>(500)</em>"
#: contrib/admin/templates/admin/500.html:10
msgid ""
@ -720,7 +728,7 @@ msgstr ""
#: contrib/admin/templates/admin/404.html:4
#: contrib/admin/templates/admin/404.html:8
msgid "Page not found"
msgstr ""
msgstr "Η σελίδα δε βρέθηκε."
#: contrib/admin/templates/admin/404.html:10
msgid "We're sorry, but the requested page could not be found."
@ -729,24 +737,24 @@ msgstr ""
#: contrib/admin/templates/admin/index.html:17
#, python-format
msgid "Models available in the %(name)s application."
msgstr ""
msgstr "Διαθέσιμα μοντέλα στην εφαρμογή %(name)s."
#: contrib/admin/templates/admin/index.html:28
#: contrib/admin/templates/admin/change_form.html:15
msgid "Add"
msgstr ""
msgstr "Προσθήκη"
#: contrib/admin/templates/admin/index.html:34
msgid "Change"
msgstr ""
msgstr "Επεξεργασία"
#: contrib/admin/templates/admin/index.html:44
msgid "You don't have permission to edit anything."
msgstr ""
msgstr "Δεν έχετε άδεια να επεξεργαστείτε τίποτα."
#: contrib/admin/templates/admin/index.html:52
msgid "Recent Actions"
msgstr ""
msgstr "Πρόσφατες Πράξεις"
#: contrib/admin/templates/admin/index.html:53
msgid "My Actions"
@ -754,16 +762,16 @@ msgstr "Οι πράξεις μου"
#: contrib/admin/templates/admin/index.html:57
msgid "None available"
msgstr ""
msgstr "Κανένα διαθέσιμο"
#: contrib/admin/templates/admin/change_list.html:11
#, python-format
msgid "Add %(name)s"
msgstr ""
msgstr "Προσθήκη %(name)s"
#: contrib/admin/templates/admin/login.html:22
msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?"
msgstr ""
msgstr "<a href=\"/password_reset/\">Ξεχάσατε τον κωδικό σας;</a> "
#: contrib/admin/templates/admin/base.html:23
msgid "Welcome,"
@ -772,7 +780,7 @@ msgstr "Καλωσήρθατε,"
#: contrib/admin/templates/admin/delete_confirmation.html:9
#: contrib/admin/templates/admin/submit_line.html:3
msgid "Delete"
msgstr ""
msgstr "Διαγραφή"
#: contrib/admin/templates/admin/delete_confirmation.html:14
#, python-format
@ -800,37 +808,37 @@ msgstr ""
#: contrib/admin/templates/admin/search_form.html:8
msgid "Go"
msgstr ""
msgstr "Πήγαινε"
#: contrib/admin/templates/admin/change_form.html:21
msgid "View on site"
msgstr ""
msgstr "Προβολή στην ιστοσελίδα"
#: contrib/admin/templates/admin/change_form.html:30
msgid "Please correct the error below."
msgid_plural "Please correct the errors below."
msgstr[0] ""
msgstr[1] ""
msgstr[0] "Παρακαλώ διορθώστε το παρακάτω λάθος."
msgstr[1] "Παρακαλώ διορθώστε τα παρακάτω λάθη."
#: contrib/admin/templates/admin/change_form.html:48
msgid "Ordering"
msgstr ""
msgstr "Σειρά"
#: contrib/admin/templates/admin/change_form.html:51
msgid "Order:"
msgstr ""
msgstr "Σειρά:"
#: contrib/admin/templates/admin/submit_line.html:4
msgid "Save as new"
msgstr ""
msgstr "Αποθήκευση καινούριου"
#: contrib/admin/templates/admin/submit_line.html:5
msgid "Save and add another"
msgstr ""
msgstr "Αποθήκευση και προσθήκη καινούριου."
#: contrib/admin/templates/admin/submit_line.html:6
msgid "Save and continue editing"
msgstr ""
msgstr "Αποθήκευση και συνέχεια επεξεργασίας"
#: contrib/admin/templates/admin/submit_line.html:7
msgid "Save"
@ -841,12 +849,12 @@ msgstr "Αποθήκευση"
#: contrib/admin/templates/registration/password_change_form.html:6
#: contrib/admin/templates/registration/password_change_form.html:10
msgid "Password change"
msgstr ""
msgstr "Αλλαγή Κωδικού"
#: contrib/admin/templates/registration/password_change_done.html:6
#: contrib/admin/templates/registration/password_change_done.html:10
msgid "Password change successful"
msgstr ""
msgstr "Αλλαγή κωδικού επιτυχής"
#: contrib/admin/templates/registration/password_change_done.html:12
msgid "Your password was changed."
@ -857,7 +865,7 @@ msgstr "Ο κωδίκός σας άλλαξε."
#: contrib/admin/templates/registration/password_reset_form.html:10
#: contrib/admin/templates/registration/password_reset_done.html:4
msgid "Password reset"
msgstr ""
msgstr "Επαναφορά κωδικού"
#: contrib/admin/templates/registration/password_reset_form.html:12
msgid ""
@ -867,11 +875,11 @@ msgstr ""
#: contrib/admin/templates/registration/password_reset_form.html:16
msgid "E-mail address:"
msgstr ""
msgstr "E-mail διεύθυνση:"
#: contrib/admin/templates/registration/password_reset_form.html:16
msgid "Reset my password"
msgstr ""
msgstr "Επαναφορά του κωδικού μου"
#: contrib/admin/templates/registration/logged_out.html:8
msgid "Thanks for spending some quality time with the Web site today."
@ -880,7 +888,7 @@ msgstr ""
#: contrib/admin/templates/registration/logged_out.html:10
msgid "Log in again"
msgstr ""
msgstr "Εισαγωγή ξανά"
#: contrib/admin/templates/registration/password_reset_done.html:6
#: contrib/admin/templates/registration/password_reset_done.html:10
@ -909,11 +917,11 @@ msgstr "Νέος κωδικός:"
#: contrib/admin/templates/registration/password_change_form.html:21
msgid "Confirm password:"
msgstr ""
msgstr "Επιβεβαίωση κωδικού"
#: contrib/admin/templates/registration/password_change_form.html:23
msgid "Change my password"
msgstr ""
msgstr "Αλλαγή του κωδικού μου"
#: contrib/admin/templates/registration/password_reset_email.html:2
msgid "You're receiving this e-mail because you requested a password reset"
@ -1003,19 +1011,19 @@ msgstr ""
#: contrib/admin/templates/widget/date_time.html:3
msgid "Date:"
msgstr ""
msgstr "Ημ/νία:"
#: contrib/admin/templates/widget/date_time.html:4
msgid "Time:"
msgstr ""
msgstr "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Ώρα:"
#: contrib/admin/templates/widget/file.html:2
msgid "Currently:"
msgstr ""
msgstr "Τρέχον:"
#: contrib/admin/templates/widget/file.html:3
msgid "Change:"
msgstr ""
msgstr "Αλλαγή:"
#: contrib/redirects/models.py:7
msgid "redirect from"
@ -1271,192 +1279,192 @@ msgstr "P"
#: utils/dates.py:6
msgid "Monday"
msgstr ""
msgstr "Δευτέρα"
#: utils/dates.py:6
msgid "Tuesday"
msgstr ""
msgstr "Τρίτη"
#: utils/dates.py:6
msgid "Wednesday"
msgstr ""
msgstr "Τετάρτη"
#: utils/dates.py:6
msgid "Thursday"
msgstr ""
msgstr "Πέμπτη"
#: utils/dates.py:6
msgid "Friday"
msgstr ""
msgstr "Παρασκευή"
#: utils/dates.py:7
msgid "Saturday"
msgstr ""
msgstr "Σάββατο"
#: utils/dates.py:7
msgid "Sunday"
msgstr ""
msgstr "Κυριακή"
#: utils/dates.py:14
msgid "January"
msgstr ""
msgstr "Ιανουάριος"
#: utils/dates.py:14
msgid "February"
msgstr ""
msgstr "Φεβρουάριος"
#: utils/dates.py:14 utils/dates.py:27
msgid "March"
msgstr ""
msgstr "Μάρτιος"
#: utils/dates.py:14 utils/dates.py:27
msgid "April"
msgstr ""
msgstr "Απρίλιος"
#: utils/dates.py:14 utils/dates.py:27
msgid "May"
msgstr ""
msgstr "Μάιος"
#: utils/dates.py:14 utils/dates.py:27
msgid "June"
msgstr ""
msgstr "Ιούνιος"
#: utils/dates.py:15 utils/dates.py:27
msgid "July"
msgstr ""
msgstr "Ιούλιος"
#: utils/dates.py:15
msgid "August"
msgstr ""
msgstr "Αύγουστος"
#: utils/dates.py:15
msgid "September"
msgstr ""
msgstr "Σεπτέμβριος"
#: utils/dates.py:15
msgid "October"
msgstr ""
msgstr "Οκτώβριος"
#: utils/dates.py:15
msgid "November"
msgstr ""
msgstr "Νοέμβριος"
#: utils/dates.py:16
msgid "December"
msgstr ""
msgstr "Δεκέμβριος"
#: utils/dates.py:19
#, fuzzy
msgid "jan"
msgstr "και"
msgstr "Ιαν"
#: utils/dates.py:19
msgid "feb"
msgstr ""
msgstr "Φεβ"
#: utils/dates.py:19
msgid "mar"
msgstr ""
msgstr "Μάρ"
#: utils/dates.py:19
msgid "apr"
msgstr ""
msgstr "Απρ"
#: utils/dates.py:19
msgid "may"
msgstr ""
msgstr "Μάι"
#: utils/dates.py:19
msgid "jun"
msgstr ""
msgstr "Ιούν"
#: utils/dates.py:20
msgid "jul"
msgstr ""
msgstr "Ιούλ"
#: utils/dates.py:20
msgid "aug"
msgstr ""
msgstr "Αύγ"
#: utils/dates.py:20
msgid "sep"
msgstr ""
msgstr "Σεπ"
#: utils/dates.py:20
msgid "oct"
msgstr ""
msgstr "Οκτ"
#: utils/dates.py:20
msgid "nov"
msgstr ""
msgstr "Νοέ"
#: utils/dates.py:20
msgid "dec"
msgstr ""
msgstr "Δεκ"
#: utils/dates.py:27
msgid "Jan."
msgstr ""
msgstr "Ιάν."
#: utils/dates.py:27
msgid "Feb."
msgstr ""
msgstr "Φεβ."
#: utils/dates.py:28
msgid "Aug."
msgstr ""
msgstr "Αύγ."
#: utils/dates.py:28
msgid "Sept."
msgstr ""
msgstr "Σεπτ."
#: utils/dates.py:28
msgid "Oct."
msgstr ""
msgstr "Οκτ."
#: utils/dates.py:28
msgid "Nov."
msgstr ""
msgstr "Νοέ."
#: utils/dates.py:28
msgid "Dec."
msgstr ""
msgstr "Δεκ."
#: utils/timesince.py:12
msgid "year"
msgid_plural "years"
msgstr[0] ""
msgstr[1] ""
msgstr[0] "χρόνος"
msgstr[1] "χρόνια"
#: utils/timesince.py:13
msgid "month"
msgid_plural "months"
msgstr[0] ""
msgstr[1] ""
msgstr[0] "μήνας"
msgstr[1] "μήνες"
#: utils/timesince.py:14
msgid "week"
msgid_plural "weeks"
msgstr[0] ""
msgstr[1] ""
msgstr[0] "εβδομάδα"
msgstr[1] "εβδομάδες"
#: utils/timesince.py:15
msgid "day"
msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
msgstr[0] "ημέρα"
msgstr[1] "ημέρες"
#: utils/timesince.py:16
msgid "hour"
msgid_plural "hours"
msgstr[0] ""
msgstr[1] ""
msgstr[0] "ώρα"
msgstr[1] "ώρες"
#: utils/timesince.py:17
msgid "minute"
msgid_plural "minutes"
msgstr[0] ""
msgstr[1] ""
msgstr[0] "λεπτό"
msgstr[1] "λεπτά"
#: conf/global_settings.py:37
msgid "Bengali"
@ -1630,7 +1638,7 @@ msgstr ""
#: core/validators.py:136
msgid "Enter a valid e-mail address."
msgstr ""
msgstr "Εισάγετε ένα σωστό e-mail."
#: core/validators.py:148
msgid ""
@ -1745,12 +1753,12 @@ msgstr[1] ""
#: core/validators.py:362
#, python-format
msgid "Make sure your uploaded file is at least %s bytes big."
msgstr "Σιγουρευτείτε ότι το αρχείου που ανεβάζετε είναι %s bytes τουλάχιστον."
msgstr "Σιγουρευτείτε ότι το αρχείο που ανεβάζετε είναι %s bytes τουλάχιστον."
#: core/validators.py:363
#, python-format
msgid "Make sure your uploaded file is at most %s bytes big."
msgstr ""
msgstr "Σιγουρευτείτε ότι το αρχείο που ανεβάζετε έχει μέγεθος μέχρι %s bytes."
#: core/validators.py:376
msgid "The format for this field is wrong."
@ -1827,7 +1835,7 @@ msgstr ""
#: db/models/fields/__init__.py:542 db/models/fields/__init__.py:553
#: forms/__init__.py:346
msgid "This field is required."
msgstr ""
msgstr "Αυτό το πεδίο είναι απαραίτητο"
#: db/models/fields/__init__.py:337
msgid "This value must be an integer."
@ -1836,12 +1844,12 @@ msgstr ""
#: db/models/fields/__init__.py:369
#, fuzzy
msgid "This value must be either True or False."
msgstr "Boolean (Είτε Αλήθεια ή Ψέμα)"
msgstr "Boolean (Είτε Αληθές ή Ψευδές)"
#: db/models/fields/__init__.py:385
#, fuzzy
msgid "This field cannot be null."
msgstr "Αυτό το πεδίο είναι άκυρο"
msgstr "Αυτό το πεδίο δεν μπορεί να είναι κενό (null)"
#: db/models/fields/__init__.py:562
msgid "Enter a valid filename."
@ -1850,7 +1858,7 @@ msgstr "Εισάγετε ένα έγκυρο όνομα αρχείου"
#: db/models/fields/related.py:43
#, python-format
msgid "Please enter a valid %s."
msgstr ""
msgstr "Παρακαλώ εισάγετε ένα/μία έγκυρο/η %s"
#: db/models/fields/related.py:579
#, fuzzy

Binary file not shown.

View File

@ -0,0 +1,109 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) 2006 and beyond.
# This file is distributed under the same license as the Django package.
# Orestis Markou <orestis@orestis.gr>, 2006.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2005-12-09 11:51+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Orestis Markou <orestis@orestis.gr>\n"
"Language-Team: Greek\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: contrib/admin/media/js/SelectFilter2.js:33
#, perl-format
msgid "Available %s"
msgstr "Διαθέσιμο %s"
#: contrib/admin/media/js/SelectFilter2.js:41
msgid "Choose all"
msgstr "Επιλογή Όλων"
#: contrib/admin/media/js/SelectFilter2.js:46
msgid "Add"
msgstr "Προσθήκη"
#: contrib/admin/media/js/SelectFilter2.js:48
msgid "Remove"
msgstr "Αφαίρεση"
#: contrib/admin/media/js/SelectFilter2.js:53
#, perl-format
msgid "Chosen %s"
msgstr "Επιλεχθέντα %s"
#: contrib/admin/media/js/SelectFilter2.js:54
msgid "Select your choice(s) and click "
msgstr "Επιλέξτε και κάντε κλικ."
#: contrib/admin/media/js/SelectFilter2.js:59
msgid "Clear all"
msgstr "Καθαρισμός όλων"
#: contrib/admin/media/js/dateparse.js:26
#: contrib/admin/media/js/calendar.js:24
msgid ""
"January February March April May June July August September October November "
"December"
msgstr "Ιανουάριος Φεβρουάριος Μάρτιος Απρίλιος Μάιος Ιούνιος Ιούλιος Αύγουστος Σεπτέμβριος Οκτώβριος Νοέμβριος "
"Δεκέμβριος"
#: contrib/admin/media/js/dateparse.js:27
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
msgstr "Κυριακή Δευτέρα Τρίτη Τετάρτη Πέμπτη Παρασκευή Σάββατο"
#: contrib/admin/media/js/calendar.js:25
msgid "S M T W T F S"
msgstr "Κ Δ Τ Τ Π Π Σ"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80
msgid "Now"
msgstr "Τώρα"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:48
msgid "Clock"
msgstr "Ρολόι"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:77
msgid "Choose a time"
msgstr "Διαλέξτε ώρα"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
msgid "Midnight"
msgstr "Μεσάνυχτα"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
msgid "6 a.m."
msgstr "6 π.μ."
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
msgid "Noon"
msgstr "Μεσημέρι"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:87
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:168
msgid "Cancel"
msgstr "Άκυρο"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:111
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:162
msgid "Today"
msgstr "Σήμερα"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:114
msgid "Calendar"
msgstr "Ημερολόγιο"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:160
msgid "Yesterday"
msgstr "Χθες"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164
msgid "Tomorrow"
msgstr "Αύριο"

View File

@ -8,8 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: django\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2006-08-18 18:57-0300\n"
"PO-Revision-Date: 2006-08-21 18:06-0300\n"
"POT-Creation-Date: 2006-11-05 19:57-0300\n"
"PO-Revision-Date: 2006-11-05 20:00-0300\n"
"Last-Translator: Ramiro Morales <rm0@gmx.net>\n"
"Language-Team: Spanish <es@li.org>\n"
"MIME-Version: 1.0\n"
@ -165,10 +165,18 @@ msgstr "Fechas importantes"
msgid "Groups"
msgstr "Grupos"
#: contrib/auth/models.py:256
#: contrib/auth/models.py:258
msgid "message"
msgstr "mensaje"
#: contrib/auth/forms.py:16
msgid "The two password fields didn't match."
msgstr "Los dos campos de contraseñas no coinciden entre si."
#: contrib/auth/forms.py:24
msgid "A user with that username already exists."
msgstr "Ya existe un usuario con ese nombre."
#: contrib/auth/forms.py:52
msgid ""
"Your Web browser doesn't appear to have cookies enabled. Cookies are "
@ -189,6 +197,24 @@ msgstr ""
msgid "This account is inactive."
msgstr "Esta cuenta está inactiva"
#: contrib/auth/forms.py:84
msgid ""
"That e-mail address doesn't have an associated user account. Are you sure "
"you've registered?"
msgstr ""
"Esa dirección de e-mail no está asociada a ninguna cuenta de usuario. ¿Está "
"seguro de que ya se ha registrado?"
#: contrib/auth/forms.py:116
msgid "The two 'new password' fields didn't match."
msgstr "Los dos campos 'nueva contraseña' no coinciden entre si."
#: contrib/auth/forms.py:123
msgid "Your old password was entered incorrectly. Please enter it again."
msgstr ""
"La antigua contraseña ingresada es incorrecta. Por favor ingrésela "
"nuevamente."
#: contrib/redirects/models.py:7
msgid "redirect from"
msgstr "redirigir desde"
@ -754,13 +780,13 @@ msgstr ""
msgid "Site administration"
msgstr "Sitio administrativo"
#: contrib/admin/views/main.py:257 contrib/admin/views/auth.py:14
#: contrib/admin/views/main.py:257 contrib/admin/views/auth.py:18
#, python-format
msgid "The %(name)s \"%(obj)s\" was added successfully."
msgstr "Se agregó con éxito el %(name)s \"%(obj)s\"."
msgstr "Se agregó con éxito %(name)s \"%(obj)s\"."
#: contrib/admin/views/main.py:261 contrib/admin/views/main.py:347
#: contrib/admin/views/auth.py:19
#: contrib/admin/views/auth.py:23
msgid "You may edit it again below."
msgstr "Puede modificarlo nuevamente abajo."
@ -780,7 +806,7 @@ msgid "Added %s."
msgstr "Agregado %s."
#: contrib/admin/views/main.py:335 contrib/admin/views/main.py:337
#: contrib/admin/views/main.py:339
#: contrib/admin/views/main.py:339 db/models/manipulators.py:306
msgid "and"
msgstr "y"
@ -801,15 +827,14 @@ msgstr "No ha modificado ning
#: contrib/admin/views/main.py:345
#, python-format
msgid "The %(name)s \"%(obj)s\" was changed successfully."
msgstr "Se modificó con éxito el %(name)s \"%(obj)s."
msgstr "Se modificó con éxito %(name)s \"%(obj)s."
#: contrib/admin/views/main.py:353
#, python-format
msgid ""
"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
msgstr ""
"Se agregó con éxito el %(name)s \"%(obj)s. Puede modificarlo nuevamente "
"abajo."
"Se agregó con éxito %(name)s \"%(obj)s. Puede modificarlo nuevamente abajo."
#: contrib/admin/views/main.py:391
#, python-format
@ -829,7 +854,7 @@ msgstr "Uno o m
#: contrib/admin/views/main.py:511
#, python-format
msgid "The %(name)s \"%(obj)s\" was deleted successfully."
msgstr "Se eliminó con éxito el %(name)s \"%(obj)s\"."
msgstr "Se eliminó con éxito %(name)s \"%(obj)s\"."
#: contrib/admin/views/main.py:514
msgid "Are you sure?"
@ -850,7 +875,7 @@ msgstr "Seleccione %s"
msgid "Select %s to change"
msgstr "Seleccione %s a modificar"
#: contrib/admin/views/main.py:756
#: contrib/admin/views/main.py:758
msgid "Database error"
msgstr "Error de base de datos"
@ -977,12 +1002,12 @@ msgstr "Estado de los EEUU (dos letras may
msgid "XML text"
msgstr "Texto XML"
#: contrib/admin/views/doc.py:339
#: contrib/admin/views/doc.py:343
#, python-format
msgid "%s does not appear to be a urlpattern object"
msgstr "%s no parece ser un objeto urlpattern"
#: contrib/admin/views/auth.py:25
#: contrib/admin/views/auth.py:29
msgid "Add user"
msgstr "Agregar usuario"
@ -1181,10 +1206,6 @@ msgstr "P
msgid "We're sorry, but the requested page could not be found."
msgstr "Lo sentimos, pero no se encuentra la página solicitada."
#: contrib/admin/templates/admin/login.html:22
msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?"
msgstr "¿Ha <a href=\"/password_reset/\">olvidado su contraseña</a>?"
#: contrib/admin/templates/admin/filters.html:4
msgid "Filter"
msgstr "Filtrar"
@ -1726,123 +1747,134 @@ msgid "Argentinean Spanish"
msgstr "Español Argentino"
#: conf/global_settings.py:49
msgid "Finnish"
msgstr "Finlandés"
#: conf/global_settings.py:50
msgid "French"
msgstr "Francés"
#: conf/global_settings.py:50
#: conf/global_settings.py:51
msgid "Galician"
msgstr "Gallego"
#: conf/global_settings.py:51
#: conf/global_settings.py:52
msgid "Hungarian"
msgstr "Húngaro"
#: conf/global_settings.py:52
#: conf/global_settings.py:53
msgid "Hebrew"
msgstr "Hebreo"
#: conf/global_settings.py:53
#: conf/global_settings.py:54
msgid "Icelandic"
msgstr "Islandés"
#: conf/global_settings.py:54
#: conf/global_settings.py:55
msgid "Italian"
msgstr "Italiano"
#: conf/global_settings.py:55
#: conf/global_settings.py:56
msgid "Japanese"
msgstr "Japonés"
#: conf/global_settings.py:56
#: conf/global_settings.py:57
msgid "Dutch"
msgstr "Holandés"
#: conf/global_settings.py:57
#: conf/global_settings.py:58
msgid "Norwegian"
msgstr "Noruego"
#: conf/global_settings.py:58
#: conf/global_settings.py:59
msgid "Polish"
msgstr "Polaco"
#: conf/global_settings.py:60
msgid "Brazilian"
msgstr "Brasileño"
#: conf/global_settings.py:59
#: conf/global_settings.py:61
msgid "Romanian"
msgstr "Rumano"
#: conf/global_settings.py:60
#: conf/global_settings.py:62
msgid "Russian"
msgstr "Ruso"
#: conf/global_settings.py:61
#: conf/global_settings.py:63
msgid "Slovak"
msgstr "Eslovaco"
#: conf/global_settings.py:62
#: conf/global_settings.py:64
msgid "Slovenian"
msgstr "Esloveno"
#: conf/global_settings.py:63
#: conf/global_settings.py:65
msgid "Serbian"
msgstr "Serbio"
#: conf/global_settings.py:64
#: conf/global_settings.py:66
msgid "Swedish"
msgstr "Sueco"
#: conf/global_settings.py:65
#: conf/global_settings.py:67
msgid "Tamil"
msgstr "Tamil"
#: conf/global_settings.py:66
#: conf/global_settings.py:68
msgid "Turkish"
msgstr "Turco"
#: conf/global_settings.py:69
msgid "Ukrainian"
msgstr "Ucraniano"
#: conf/global_settings.py:67
#: conf/global_settings.py:70
msgid "Simplified Chinese"
msgstr "Chino simplificado"
#: conf/global_settings.py:68
#: conf/global_settings.py:71
msgid "Traditional Chinese"
msgstr "Chino tradicional"
#: db/models/manipulators.py:302
#: db/models/manipulators.py:305
#, python-format
msgid "%(object)s with this %(type)s already exists for the given %(field)s."
msgstr ""
"Ya existen %(object)s con este %(type)s para el %(field)s especificado."
msgstr "Ya existe un(a) %(object)s con este/a %(type)s para %(field)s."
#: db/models/fields/__init__.py:40
#: db/models/fields/__init__.py:41
#, python-format
msgid "%(optname)s with this %(fieldname)s already exists."
msgstr "Ya existe %(optname)s con este %(fieldname)s."
#: db/models/fields/__init__.py:114 db/models/fields/__init__.py:265
#: db/models/fields/__init__.py:551 db/models/fields/__init__.py:562
#: forms/__init__.py:346
#: db/models/fields/__init__.py:115 db/models/fields/__init__.py:266
#: db/models/fields/__init__.py:569 db/models/fields/__init__.py:580
#: forms/__init__.py:347
msgid "This field is required."
msgstr "Este campo es obligatorio."
#: db/models/fields/__init__.py:340
#: db/models/fields/__init__.py:349
msgid "This value must be an integer."
msgstr "Este valor debe ser un número entero."
#: db/models/fields/__init__.py:372
#: db/models/fields/__init__.py:381
msgid "This value must be either True or False."
msgstr "Este valor debe ser True o False."
#: db/models/fields/__init__.py:388
#: db/models/fields/__init__.py:397
msgid "This field cannot be null."
msgstr "Este campo no puede ser nulo."
#: db/models/fields/__init__.py:415 core/validators.py:127
#: db/models/fields/__init__.py:424 core/validators.py:146
msgid "Enter a valid date in YYYY-MM-DD format."
msgstr "Introduzca una fecha válida en formato AAAA-MM-DD."
#: db/models/fields/__init__.py:477 core/validators.py:135
#: db/models/fields/__init__.py:488 core/validators.py:155
msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format."
msgstr "Introduzca una fecha/hora válida en formato YYYY-MM-DD HH:MM."
#: db/models/fields/__init__.py:571
#: db/models/fields/__init__.py:589
msgid "Enter a valid filename."
msgstr "Introduzca un nombre de achivo válido"
@ -1859,7 +1891,8 @@ msgstr " Separe m
msgid ""
"Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
msgstr ""
"Pulse \"Control\", o \"Command\" en un Mac, para seleccionar más de uno."
"Mantenga presionada \"Control\" (\"Command\" en un Mac) para seleccionar más "
"de uno."
#: db/models/fields/related.py:664
#, python-format
@ -1873,42 +1906,42 @@ msgstr[1] ""
"Por favor, introduzca IDs de %(self)s válidos. Los valores %(value)r no son "
"válidos."
#: forms/__init__.py:381
#: forms/__init__.py:382
#, python-format
msgid "Ensure your text is less than %s character."
msgid_plural "Ensure your text is less than %s characters."
msgstr[0] "Asegúrese de que su texto tiene menos de %s carácter."
msgstr[1] "Asegúrese de que su texto tiene menos de %s caracteres."
#: forms/__init__.py:386
#: forms/__init__.py:387
msgid "Line breaks are not allowed here."
msgstr "No se permiten saltos de línea."
#: forms/__init__.py:487 forms/__init__.py:560 forms/__init__.py:599
#: forms/__init__.py:488 forms/__init__.py:561 forms/__init__.py:600
#, python-format
msgid "Select a valid choice; '%(data)s' is not in %(choices)s."
msgstr "Seleccione una opción válida; '%(data)s' no está en %(choices)s."
#: forms/__init__.py:661 core/validators.py:151 core/validators.py:379
#: forms/__init__.py:662 core/validators.py:172 core/validators.py:401
msgid "No file was submitted. Check the encoding type on the form."
msgstr ""
"No se envió un archivo. Verifique el tipo de codificación en el formulario."
#: forms/__init__.py:663
#: forms/__init__.py:664
msgid "The submitted file is empty."
msgstr "El archivo enviado está vacío."
#: forms/__init__.py:719
#: forms/__init__.py:720
msgid "Enter a whole number between -32,768 and 32,767."
msgstr "Introduzca un número entero entre -32,768 y 32,767."
msgstr "Introduzca un número entero entre -32.768 y 32.767."
#: forms/__init__.py:729
#: forms/__init__.py:730
msgid "Enter a positive number."
msgstr "Introduzca un número positivo."
#: forms/__init__.py:739
#: forms/__init__.py:740
msgid "Enter a whole number between 0 and 32,767."
msgstr "Introduzca un número entero entre 0 y 32,767."
msgstr "Introduzca un número entero entre 0 y 32.767."
#: core/validators.py:63
msgid "This value must contain only letters, numbers and underscores."
@ -1919,8 +1952,13 @@ msgid ""
"This value must contain only letters, numbers, underscores, dashes or "
"slashes."
msgstr ""
"Este valor debe contener sólo letras, números, guiones bajos, barras (/) o "
"slashes."
"Este valor debe contener sólo letras, números, guiones bajos, guiones o "
"barras (/)"
#: core/validators.py:71
msgid "This value must contain only letters, numbers, underscores or hyphens."
msgstr ""
"Este valor debe contener sólo letras, números, guiones bajos o guiones."
#: core/validators.py:75
msgid "Uppercase letters are not allowed here."
@ -1962,15 +2000,24 @@ msgstr "Introduzca un n
msgid "Only alphabetical characters are allowed here."
msgstr "Sólo se admiten caracteres alfabéticos."
#: core/validators.py:131
#: core/validators.py:138
msgid "Year must be 1900 or later."
msgstr "El año debe ser 1900 o posterior."
#: core/validators.py:142
#, python-format
msgid "Invalid date: %s."
msgstr "Fecha no válida: %s."
#: core/validators.py:151
msgid "Enter a valid time in HH:MM format."
msgstr "Introduzca una hora válida en formato HH:MM."
#: core/validators.py:139
#: core/validators.py:160
msgid "Enter a valid e-mail address."
msgstr "Introduzca una dirección de correo electrónico válida"
#: core/validators.py:155
#: core/validators.py:176
msgid ""
"Upload a valid image. The file you uploaded was either not an image or a "
"corrupted image."
@ -1978,28 +2025,28 @@ msgstr ""
"Envíe una imagen válida. El archivo que ha enviado no era una imagen o se "
"trataba de una imagen corrupta."
#: core/validators.py:162
#: core/validators.py:183
#, python-format
msgid "The URL %s does not point to a valid image."
msgstr "La URL %s no apunta a una imagen válida."
#: core/validators.py:166
#: core/validators.py:187
#, python-format
msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid."
msgstr ""
"Los números de teléfono deben guardar el formato XXX-XXX-XXXX format. \"%s\" "
"no es válido."
"Los números telefónicos deben respetar el formato XXX-XXX-XXXX. \"%s\" no es "
"válido."
#: core/validators.py:174
#: core/validators.py:195
#, python-format
msgid "The URL %s does not point to a valid QuickTime video."
msgstr "La URL %s no apunta a un vídeo QuickTime válido."
#: core/validators.py:178
#: core/validators.py:199
msgid "A valid URL is required."
msgstr "Se precisa una URL válida."
#: core/validators.py:192
#: core/validators.py:213
#, python-format
msgid ""
"Valid HTML is required. Specific errors are:\n"
@ -2008,69 +2055,69 @@ msgstr ""
"Se precisa HTML válido. Los errores específicos son:\n"
"%s"
#: core/validators.py:199
#: core/validators.py:220
#, python-format
msgid "Badly formed XML: %s"
msgstr "XML mal formado: %s"
#: core/validators.py:209
#: core/validators.py:230
#, python-format
msgid "Invalid URL: %s"
msgstr "URL no válida: %s"
#: core/validators.py:213 core/validators.py:215
#: core/validators.py:234 core/validators.py:236
#, python-format
msgid "The URL %s is a broken link."
msgstr "La URL %s es un enlace roto."
#: core/validators.py:221
#: core/validators.py:242
msgid "Enter a valid U.S. state abbreviation."
msgstr "Introduzca una abreviatura válida de estado de los EEUU."
#: core/validators.py:236
#: core/validators.py:256
#, python-format
msgid "Watch your mouth! The word %s is not allowed here."
msgid_plural "Watch your mouth! The words %s are not allowed here."
msgstr[0] "¡Vigila tu boca! Aquí no admitimos la palabra %s."
msgstr[1] "¡Vigila tu boca! Aquí no admitimos las palabras %s."
#: core/validators.py:243
#: core/validators.py:263
#, python-format
msgid "This field must match the '%s' field."
msgstr "Este campo debe concordar con el campo '%s'."
#: core/validators.py:262
#: core/validators.py:282
msgid "Please enter something for at least one field."
msgstr "Por favor, introduzca algo en al menos un campo."
#: core/validators.py:271 core/validators.py:282
#: core/validators.py:291 core/validators.py:302
msgid "Please enter both fields or leave them both empty."
msgstr "Por favor, rellene ambos campos o deje ambos vacíos."
#: core/validators.py:289
#: core/validators.py:309
#, python-format
msgid "This field must be given if %(field)s is %(value)s"
msgstr "Se debe proporcionar este campo si %(field)s es %(value)s"
#: core/validators.py:301
#: core/validators.py:321
#, python-format
msgid "This field must be given if %(field)s is not %(value)s"
msgstr "Se debe proporcionar este campo si %(field)s no es %(value)s"
#: core/validators.py:320
#: core/validators.py:340
msgid "Duplicate values are not allowed."
msgstr "No se admiten valores duplicados."
#: core/validators.py:343
#: core/validators.py:363
#, python-format
msgid "This value must be a power of %s."
msgstr "Este valor debe ser una potencia de %s."
#: core/validators.py:354
#: core/validators.py:374
msgid "Please enter a valid decimal number."
msgstr "Por favor, introduzca un número decimal válido."
#: core/validators.py:356
#: core/validators.py:378
#, python-format
msgid "Please enter a valid decimal number with at most %s total digit."
msgid_plural ""
@ -2082,7 +2129,7 @@ msgstr[1] ""
"Por favor, introduzca un número decimal válido con un maximo de %s dígitos "
"en total."
#: core/validators.py:359
#: core/validators.py:381
#, python-format
msgid ""
"Please enter a valid decimal number with a whole part of at most %s digit."
@ -2095,7 +2142,7 @@ msgstr[1] ""
"Por favor, introduzca un número decimal válido con un máximo de %s dígitos "
"enteros."
#: core/validators.py:362
#: core/validators.py:384
#, python-format
msgid "Please enter a valid decimal number with at most %s decimal place."
msgid_plural ""
@ -2107,30 +2154,30 @@ msgstr[1] ""
"Por favor, introduzca un número decimal válido con un máximo de %s "
"posiciones decimales."
#: core/validators.py:372
#: core/validators.py:394
#, python-format
msgid "Make sure your uploaded file is at least %s bytes big."
msgstr "Asegúrese de que el archivo que envía tiene al menos %s bytes."
#: core/validators.py:373
#: core/validators.py:395
#, python-format
msgid "Make sure your uploaded file is at most %s bytes big."
msgstr "Asegúrese de que el archivo que envía tiene como máximo %s bytes."
#: core/validators.py:390
#: core/validators.py:412
msgid "The format for this field is wrong."
msgstr "El formato de este campo es incorrecto."
#: core/validators.py:405
#: core/validators.py:427
msgid "This field is invalid."
msgstr "Este campo no es válido."
#: core/validators.py:441
#: core/validators.py:463
#, python-format
msgid "Could not retrieve anything from %s."
msgstr "No pude obtener nada de %s."
#: core/validators.py:444
#: core/validators.py:466
#, python-format
msgid ""
"The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
@ -2138,7 +2185,7 @@ msgstr ""
"La URL %(url)s devolvió la cabecera Content-Type '%(contenttype)s', que no "
"es válida."
#: core/validators.py:477
#: core/validators.py:499
#, python-format
msgid ""
"Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with "
@ -2147,7 +2194,7 @@ msgstr ""
"Por favor, cierre la etiqueta %(tag)s de la línea %(line)s. (La línea "
"empieza por \"%(start)s\".)"
#: core/validators.py:481
#: core/validators.py:503
#, python-format
msgid ""
"Some text starting on line %(line)s is not allowed in that context. (Line "
@ -2156,7 +2203,7 @@ msgstr ""
"Parte del texto que comienza en la línea %(line)s no está permitido en ese "
"contexto. (La línea empieza por \"%(start)s\".)"
#: core/validators.py:486
#: core/validators.py:508
#, python-format
msgid ""
"\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%"
@ -2165,7 +2212,7 @@ msgstr ""
"El \"%(attr)s\" de la línea %(line)s no es un atributo válido. (La línea "
"empieza por \"%(start)s\".)"
#: core/validators.py:491
#: core/validators.py:513
#, python-format
msgid ""
"\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%"
@ -2174,7 +2221,7 @@ msgstr ""
"La \"<%(tag)s>\" de la línea %(line)s no es una etiqueta válida. (La línea "
"empieza por \"%(start)s\".)"
#: core/validators.py:495
#: core/validators.py:517
#, python-format
msgid ""
"A tag on line %(line)s is missing one or more required attributes. (Line "
@ -2183,7 +2230,7 @@ msgstr ""
"A una etiqueta de la línea %(line)s le faltan uno o más atributos "
"requeridos. (La línea empieza por \"%(start)s\".)"
#: core/validators.py:500
#: core/validators.py:522
#, python-format
msgid ""
"The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line "
@ -2199,17 +2246,20 @@ msgstr "si,no,tal vez"
#: views/generic/create_update.py:43
#, python-format
msgid "The %(verbose_name)s was created successfully."
msgstr "Se creó con éxito el %(verbose_name)."
msgstr "Se creó con éxito %(verbose_name)."
#: views/generic/create_update.py:117
#, python-format
msgid "The %(verbose_name)s was updated successfully."
msgstr "Se actualizó con éxito el %(verbose_name)s."
msgstr "Se actualizó con éxito %(verbose_name)s."
#: views/generic/create_update.py:184
#, python-format
msgid "The %(verbose_name)s was deleted."
msgstr "Se eliminó el %(verbose_name)s."
msgstr "Se eliminó %(verbose_name)s."
#~ msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?"
#~ msgstr "¿Ha <a href=\"/password_reset/\">olvidado su contraseña</a>?"
#~ msgid "%(content_type_name)s"
#~ msgstr "tipos de contenido"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Django JavaScript 1.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2006-06-19 12:15-0300\n"
"POT-Creation-Date: 2006-09-25 15:09-0300\n"
"PO-Revision-Date: 2006-05-16 10:20-0300\n"
"Last-Translator: Ramiro Morales <rm0@gmx.net>\n"
"MIME-Version: 1.0\n"
@ -39,7 +39,7 @@ msgstr "%s elegidos"
#: contrib/admin/media/js/SelectFilter2.js:54
msgid "Select your choice(s) and click "
msgstr "Haga sus elecciones y haga click en "
msgstr "Seleccione los items a agregar y haga click en "
#: contrib/admin/media/js/SelectFilter2.js:59
msgid "Clear all"
@ -51,7 +51,7 @@ msgid ""
"January February March April May June July August September October November "
"December"
msgstr ""
"Enero Febrero Marzo Abril Mayo Junio Julio Agosto Septiembre Octubre "
"Enero Febrero Marzo Abril Mayo Junio Julio Agosto Setiembre Octubre "
"Noviembre Diciembre"
#: contrib/admin/media/js/dateparse.js:33
@ -71,49 +71,49 @@ msgstr "Mostrar"
msgid "Hide"
msgstr "Ocultar"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:89
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:47
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
msgid "Now"
msgstr "Ahora"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:48
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:51
msgid "Clock"
msgstr "Reloj"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:86
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:78
msgid "Choose a time"
msgstr "Elija una hora"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:90
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
msgid "Midnight"
msgstr "Medianoche"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:91
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
msgid "6 a.m."
msgstr "6 a.m."
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:92
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:84
msgid "Noon"
msgstr "Mediodía"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:96
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:187
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:88
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
msgid "Cancel"
msgstr "Cancelar"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:120
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:181
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:128
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:177
msgid "Today"
msgstr "Hoy"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:123
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:132
msgid "Calendar"
msgstr "Calendario"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:175
msgid "Yesterday"
msgstr "Ayer"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
msgid "Tomorrow"
msgstr "Mañana"

View File

@ -2,14 +2,15 @@
# Copyright (C) 2006 THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# João Marcus Christ <joaoma@gmail.com>, 2006.
# Carlos Eduardo de Paula <carlosedp@gmail.com>, 2006.
#
msgid ""
msgstr ""
"Project-Id-Version: django\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2006-05-16 10:11+0200\n"
"PO-Revision-Date: 2006-01-23 19:54-0200\n"
"Last-Translator: João Marcus Christ <joaoma@gmail.com>\n"
"PO-Revision-Date: 2006-11-01 17:45-0300\n"
"Last-Translator: Carlos Eduardo de Paula <carlosedp@gmail.com>\n"
"Language-Team: Português do Brasil <pt-br@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -86,12 +87,12 @@ msgid ""
"removed\" message will be displayed instead."
msgstr ""
"Selecione esta opção se o comentário é inapropriado. Uma mensagem \"Este "
"comentário foi removido\" será mostrada no lugar."
"comentário foi removido\" a mensagem será mostrada no lugar."
#: contrib/comments/models.py:91
#, fuzzy
msgid "comments"
msgstr "comentário"
msgstr "comentários"
#: contrib/comments/models.py:131 contrib/comments/models.py:207
msgid "Content object"
@ -150,7 +151,7 @@ msgstr "Pontuação de Karma"
#: contrib/comments/models.py:238
#, fuzzy
msgid "karma scores"
msgstr "Pontuação de Karma"
msgstr "Pontuações de Karma"
#: contrib/comments/models.py:242
#, python-format
@ -170,17 +171,17 @@ msgstr ""
#: contrib/comments/models.py:265
msgid "flag date"
msgstr "marca de data"
msgstr "flag de data"
#: contrib/comments/models.py:268
#, fuzzy
msgid "user flag"
msgstr "Flag de usuário"
msgstr "flag de usuário"
#: contrib/comments/models.py:269
#, fuzzy
msgid "user flags"
msgstr "Flags de usuário"
msgstr "flags de usuário"
#: contrib/comments/models.py:273
#, python-format
@ -189,22 +190,22 @@ msgstr "Flag por %r"
#: contrib/comments/models.py:278
msgid "deletion date"
msgstr "data de apagamento"
msgstr "data de exclusão"
#: contrib/comments/models.py:280
#, fuzzy
msgid "moderator deletion"
msgstr "Apagamento feito por moderador"
msgstr "Exclusão feita pelo moderador"
#: contrib/comments/models.py:281
#, fuzzy
msgid "moderator deletions"
msgstr "Apagamentos feitos por moderador"
msgstr "Exclusões feitas pelo moderador"
#: contrib/comments/models.py:285
#, python-format
msgid "Moderator deletion by %r"
msgstr "Apagamento feito pelo moderador %r"
msgstr "Exclusao feita pelo moderador %r"
#: contrib/comments/views/karma.py:19
msgid "Anonymous users cannot vote"
@ -237,12 +238,12 @@ msgid_plural ""
"\n"
"%(text)s"
msgstr[0] ""
"Este comentário foi feito por um usuário esboço:\n"
"\n"
"Este comentário foi feito por um usuário que postou menos de %(count)s "
"comentário:\n"
"%(text)s"
msgstr[1] ""
"Este comentário foi feito por um usuário esboço:\n"
"\n"
"Este comentário foi feito por um usuário que postou menos de %(count)s "
"comentários:\n"
"%(text)s"
#: contrib/comments/views/comments.py:117
@ -252,7 +253,7 @@ msgid ""
"\n"
"%(text)s"
msgstr ""
"Este comentário foi feito por um usuário esboço:\n"
"Este comentário foi feito por um usuário incompleto:\n"
"\n"
"%(text)s"
@ -299,7 +300,7 @@ msgstr "Senha:"
#: contrib/comments/templates/comments/form.html:6
#, fuzzy
msgid "Forgotten your password?"
msgstr "Alterar minha senha"
msgstr "Esqueceu sua senha?"
#: contrib/comments/templates/comments/form.html:8
#: contrib/admin/templates/admin/object_history.html:3
@ -325,21 +326,21 @@ msgstr "Encerrar sessão"
#: contrib/comments/templates/comments/form.html:12
#, fuzzy
msgid "Ratings"
msgstr "avaliação #1"
msgstr "Avaliações"
#: contrib/comments/templates/comments/form.html:12
#: contrib/comments/templates/comments/form.html:23
msgid "Required"
msgstr ""
msgstr "Requerido"
#: contrib/comments/templates/comments/form.html:12
#: contrib/comments/templates/comments/form.html:23
msgid "Optional"
msgstr ""
msgstr "Opcional"
#: contrib/comments/templates/comments/form.html:23
msgid "Post a photo"
msgstr ""
msgstr "Postar uma foto"
#: contrib/comments/templates/comments/form.html:27
#: contrib/comments/templates/comments/freeform.html:5
@ -351,12 +352,12 @@ msgstr "Comentário"
#: contrib/comments/templates/comments/freeform.html:9
#, fuzzy
msgid "Preview comment"
msgstr "Comentário livre"
msgstr "Pré visualizar comentário"
#: contrib/comments/templates/comments/freeform.html:4
#, fuzzy
msgid "Your name:"
msgstr "usuário"
msgstr "Seu nome:"
#: contrib/admin/filterspecs.py:40
#, python-format
@ -443,7 +444,7 @@ msgid ""
"sensitive."
msgstr ""
"Por favor entre usuário e senha corretos. Note que ambos os "
"camposdiferenciam maiúsculas e minúsculas."
"campos diferenciam maiúsculas e minúsculas."
#: contrib/admin/views/decorators.py:23
#: contrib/admin/templates/admin/login.html:25
@ -468,7 +469,7 @@ msgstr ""
#: contrib/admin/views/decorators.py:82
msgid "Usernames cannot contain the '@' character."
msgstr "Nomes de usuário não podem conter o caracter '@'."
msgstr "Nomes de usuário não podem conter o caractere '@'."
#: contrib/admin/views/decorators.py:84
#, python-format
@ -553,7 +554,7 @@ msgstr "Um(a) ou mais %(fieldname)s em %(name)s:"
#: contrib/admin/views/main.py:508
#, python-format
msgid "The %(name)s \"%(obj)s\" was deleted successfully."
msgstr "O(A) %(name)s \"%(obj)s\" foi adicionado com sucesso."
msgstr "O(A) %(name)s \"%(obj)s\" foi excluído com sucesso."
#: contrib/admin/views/main.py:511
msgid "Are you sure?"
@ -746,7 +747,7 @@ msgid ""
"mail and should be fixed shortly. Thanks for your patience."
msgstr ""
"Houve um erro. Este foi reportado aos administradores do site através d e-"
"mail e deve ser consertado em breve. Obrigado pela compreensão."
"mail e deve ser corrigido em breve. Obrigado pela compreensão."
#: contrib/admin/templates/admin/404.html:4
#: contrib/admin/templates/admin/404.html:8
@ -760,7 +761,7 @@ msgstr "Desculpe, mas a página requisitada não pode ser encontrada."
#: contrib/admin/templates/admin/index.html:17
#, python-format
msgid "Models available in the %(name)s application."
msgstr ""
msgstr "Modelos disponíveis na aplicação %(name)s"
#: contrib/admin/templates/admin/index.html:28
#: contrib/admin/templates/admin/change_form.html:15
@ -794,7 +795,7 @@ msgstr "Adicionar %(name)s"
#: contrib/admin/templates/admin/login.html:22
msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?"
msgstr "Você <a href=\"/password_reset/\"esqueceu a senha</a>?"
msgstr "Você <a href=\"/password_reset/\">esqueceu sua senha</a>?"
#: contrib/admin/templates/admin/base.html:23
msgid "Welcome,"
@ -836,7 +837,7 @@ msgstr "Por %(title)s "
#: contrib/admin/templates/admin/search_form.html:8
msgid "Go"
msgstr ""
msgstr "Ir"
#: contrib/admin/templates/admin/change_form.html:21
msgid "View on site"
@ -847,7 +848,7 @@ msgstr "Ver no site"
msgid "Please correct the error below."
msgid_plural "Please correct the errors below."
msgstr[0] "Por favor, corrija o erro abaixo."
msgstr[1] "Por favor, corrija o erro abaixo."
msgstr[1] "Por favor, corrija os erros abaixo."
#: contrib/admin/templates/admin/change_form.html:48
msgid "Ordering"
@ -930,8 +931,8 @@ msgid ""
"We've e-mailed a new password to the e-mail address you submitted. You "
"should be receiving it shortly."
msgstr ""
"Nós enviamos uma nova senha para o e-mail que você informou. Você deve estar "
"recebendo uma mensagem em breve."
"Nós enviamos uma nova senha para o e-mail que você informou. Você deverá "
"receber uma mensagem em breve."
#: contrib/admin/templates/registration/password_change_form.html:12
msgid ""
@ -973,7 +974,7 @@ msgstr "Sua nova senha é: %(new_password)s"
#: contrib/admin/templates/registration/password_reset_email.html:7
msgid "Feel free to change this password by going to this page:"
msgstr "Sinta-se livre para alterar esta senha visitando esta página:"
msgstr "Sinta-se a vontade para alterar esta senha visitando esta página:"
#: contrib/admin/templates/registration/password_reset_email.html:11
msgid "Your username, in case you've forgotten:"
@ -1040,17 +1041,17 @@ msgstr ""
#: contrib/admin/templates/admin_doc/bookmarklets.html:25
msgid "Edit this object (current window)"
msgstr "Edita este objeto (janela atual)"
msgstr "Editar este objeto (janela atual)"
#: contrib/admin/templates/admin_doc/bookmarklets.html:26
msgid "Jumps to the admin page for pages that represent a single object."
msgstr ""
"Vai para a página de administração para páginas que representam um objeto "
"Vai para a página de administração que representam um objeto "
"único."
#: contrib/admin/templates/admin_doc/bookmarklets.html:28
msgid "Edit this object (new window)"
msgstr "Edita este objeto (nova janela)"
msgstr "Editar este objeto (nova janela)"
#: contrib/admin/templates/admin_doc/bookmarklets.html:29
msgid "As above, but opens the admin page in a new window."
@ -1135,7 +1136,7 @@ msgstr ""
#: contrib/flatpages/models.py:14
msgid "registration required"
msgstr "é obrigatório registrar"
msgstr "registro obrigatório"
#: contrib/flatpages/models.py:14
msgid "If this is checked, only logged-in users will be able to view the page."
@ -1160,22 +1161,22 @@ msgstr "nome código"
#: contrib/auth/models.py:17
#, fuzzy
msgid "permission"
msgstr "Permissão"
msgstr "permissão"
#: contrib/auth/models.py:18 contrib/auth/models.py:27
#, fuzzy
msgid "permissions"
msgstr "Permissões"
msgstr "permissões"
#: contrib/auth/models.py:29
#, fuzzy
msgid "group"
msgstr "Grupo"
msgstr "grupo"
#: contrib/auth/models.py:30 contrib/auth/models.py:65
#, fuzzy
msgid "groups"
msgstr "Grupos"
msgstr "grupos"
#: contrib/auth/models.py:55
msgid "username"
@ -1236,17 +1237,17 @@ msgstr ""
#: contrib/auth/models.py:67
#, fuzzy
msgid "user permissions"
msgstr "Permissões"
msgstr "permissões do usuário"
#: contrib/auth/models.py:70
#, fuzzy
msgid "user"
msgstr "Usuário"
msgstr "usuário"
#: contrib/auth/models.py:71
#, fuzzy
msgid "users"
msgstr "Usuários"
msgstr "usuários"
#: contrib/auth/models.py:76
msgid "Personal info"
@ -1267,7 +1268,7 @@ msgstr "Grupos"
#: contrib/auth/models.py:219
#, fuzzy
msgid "message"
msgstr "Mensagem"
msgstr "mensagem"
#: contrib/auth/forms.py:30
msgid ""
@ -1275,7 +1276,7 @@ msgid ""
"required for logging in."
msgstr ""
"Seu navegador Web não parece estar com os cookies habilitados. Cookies são "
"requeridos para acesssar."
"requeridos para acessar."
#: contrib/contenttypes/models.py:25
#, fuzzy
@ -1417,52 +1418,52 @@ msgstr "Dezembro"
#: utils/dates.py:19
#, fuzzy
msgid "jan"
msgstr "e"
msgstr "jan"
#: utils/dates.py:19
msgid "feb"
msgstr ""
msgstr "fev"
#: utils/dates.py:19
msgid "mar"
msgstr ""
msgstr "mar"
#: utils/dates.py:19
msgid "apr"
msgstr ""
msgstr "abr"
#: utils/dates.py:19
#, fuzzy
msgid "may"
msgstr "dia"
msgstr "mai"
#: utils/dates.py:19
msgid "jun"
msgstr ""
msgstr "jun"
#: utils/dates.py:20
msgid "jul"
msgstr ""
msgstr "jul"
#: utils/dates.py:20
msgid "aug"
msgstr ""
msgstr "ago"
#: utils/dates.py:20
msgid "sep"
msgstr ""
msgstr "set"
#: utils/dates.py:20
msgid "oct"
msgstr ""
msgstr "out"
#: utils/dates.py:20
msgid "nov"
msgstr ""
msgstr "nov"
#: utils/dates.py:20
msgid "dec"
msgstr ""
msgstr "dez"
#: utils/dates.py:27
msgid "Jan."
@ -1497,45 +1498,45 @@ msgstr "Dez."
msgid "year"
msgid_plural "years"
msgstr[0] "ano"
msgstr[1] "ano"
msgstr[1] "anos"
#: utils/timesince.py:13
#, fuzzy
msgid "month"
msgid_plural "months"
msgstr[0] "mês"
msgstr[1] "mês"
msgstr[1] "meses"
#: utils/timesince.py:14
msgid "week"
msgid_plural "weeks"
msgstr[0] ""
msgstr[1] ""
msgstr[0] "semana"
msgstr[1] "semanas"
#: utils/timesince.py:15
#, fuzzy
msgid "day"
msgid_plural "days"
msgstr[0] "dia"
msgstr[1] "dia"
msgstr[1] "dias"
#: utils/timesince.py:16
#, fuzzy
msgid "hour"
msgid_plural "hours"
msgstr[0] "hora"
msgstr[1] "hora"
msgstr[1] "horas"
#: utils/timesince.py:17
#, fuzzy
msgid "minute"
msgid_plural "minutes"
msgstr[0] "minuto"
msgstr[1] "minuto"
msgstr[1] "minutos"
#: conf/global_settings.py:37
msgid "Bengali"
msgstr ""
msgstr "Bengalês"
#: conf/global_settings.py:38
msgid "Czech"
@ -1548,7 +1549,7 @@ msgstr ""
#: conf/global_settings.py:40
#, fuzzy
msgid "Danish"
msgstr "Espanhol"
msgstr "Dinamarquês"
#: conf/global_settings.py:41
msgid "German"
@ -1556,7 +1557,7 @@ msgstr "Alemão"
#: conf/global_settings.py:42
msgid "Greek"
msgstr ""
msgstr "Grego"
#: conf/global_settings.py:43
msgid "English"
@ -1576,11 +1577,11 @@ msgstr "Galiciano"
#: conf/global_settings.py:47
msgid "Hungarian"
msgstr ""
msgstr "Húngaro"
#: conf/global_settings.py:48
msgid "Hebrew"
msgstr ""
msgstr "Hebraico"
#: conf/global_settings.py:49
msgid "Icelandic"
@ -1604,7 +1605,7 @@ msgstr "Norueguês"
#: conf/global_settings.py:54
msgid "Brazilian"
msgstr "Brazileiro"
msgstr "Brasileiro"
#: conf/global_settings.py:55
msgid "Romanian"
@ -1621,7 +1622,7 @@ msgstr "Eslovaco"
#: conf/global_settings.py:58
#, fuzzy
msgid "Slovenian"
msgstr "Eslovaco"
msgstr "Esloveno"
#: conf/global_settings.py:59
msgid "Serbian"
@ -1634,7 +1635,7 @@ msgstr "Sueco"
#: conf/global_settings.py:61
#, fuzzy
msgid "Ukrainian"
msgstr "Brazileiro"
msgstr "Ucraniano"
#: conf/global_settings.py:62
msgid "Simplified Chinese"
@ -1689,7 +1690,7 @@ msgstr "Este valor não pode conter apenas dígitos."
#: core/validators.py:116
msgid "Enter a whole number."
msgstr "Informe um número inteiro."
msgstr "Informe um número completo."
#: core/validators.py:120
msgid "Only alphabetical characters are allowed here."
@ -1772,7 +1773,7 @@ msgstr "Informe uma abreviação válida de nome de um estado dos EUA."
msgid "Watch your mouth! The word %s is not allowed here."
msgid_plural "Watch your mouth! The words %s are not allowed here."
msgstr[0] "Lave sua boca! A palavra %s não é permitida aqui."
msgstr[1] "Lave sua boca! A palavra %s não é permitida aqui."
msgstr[1] "Lave sua boca! As palavras %s não são permitidas aqui."
#: core/validators.py:236
#, python-format
@ -1808,14 +1809,14 @@ msgstr "Este valor deve ser uma potência de %s."
#: core/validators.py:347
msgid "Please enter a valid decimal number."
msgstr "Informe um número decimal."
msgstr "Informe um número decimal válido."
#: core/validators.py:349
#, fuzzy, python-format
msgid "Please enter a valid decimal number with at most %s total digit."
msgid_plural ""
"Please enter a valid decimal number with at most %s total digits."
msgstr[0] "Por favor entre com um número decimal com no máximo %s digitos."
msgstr[0] "Por favor entre com um número decimal com no máximo %s digito."
msgstr[1] "Por favor entre com um número decimal com no máximo %s digitos."
#: core/validators.py:352
@ -1824,7 +1825,7 @@ msgid "Please enter a valid decimal number with at most %s decimal place."
msgid_plural ""
"Please enter a valid decimal number with at most %s decimal places."
msgstr[0] "Informe um número decimal com no máximo %s casa decimal."
msgstr[1] "Informe um número decimal com no máximo %s casa decimal."
msgstr[1] "Informe um número decimal com no máximo %s casas decimais."
#: core/validators.py:362
#, python-format
@ -1930,17 +1931,17 @@ msgstr "Este campo é requerido."
#: db/models/fields/__init__.py:337
#, fuzzy
msgid "This value must be an integer."
msgstr "Este valor deve ser uma potência de %s."
msgstr "Este valor deve ser um inteiro."
#: db/models/fields/__init__.py:369
#, fuzzy
msgid "This value must be either True or False."
msgstr "Este valor deve ser uma potência de %s."
msgstr "Este valor deve ser Verdadeiro ou Falso."
#: db/models/fields/__init__.py:385
#, fuzzy
msgid "This field cannot be null."
msgstr "Este campo é inválido."
msgstr "Este campo não pode ser nulo."
#: db/models/fields/__init__.py:562
msgid "Enter a valid filename."
@ -1954,14 +1955,14 @@ msgstr "Por favor informe um %s válido."
#: db/models/fields/related.py:579
#, fuzzy
msgid "Separate multiple IDs with commas."
msgstr " Separe IDs múltiplos com vírgulas."
msgstr "Separe IDs múltiplos com vírgulas."
#: db/models/fields/related.py:581
#, fuzzy
msgid ""
"Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
msgstr ""
" Mantenha pressionado \"Control\", ou \"Command\" num Mac para selecionar "
" Mantenha pressionado \"Control\", ou \"Command\" no Mac para selecionar "
"mais de uma opção."
#: db/models/fields/related.py:625
@ -1972,18 +1973,18 @@ msgid_plural ""
msgstr[0] ""
"Por favor, entre IDs válidos para %(self)s. O valor %(value)r é inválido."
msgstr[1] ""
"Por favor, entre IDs válidos para %(self)s. O valor %(value)r é inválido."
"Por favor, entre IDs válidos para %(self)s. Os valores %(value)r são inválidos."
#: forms/__init__.py:380
#, fuzzy, python-format
msgid "Ensure your text is less than %s character."
msgid_plural "Ensure your text is less than %s characters."
msgstr[0] "Certifique-se de que seu texto tenha menos que %s caracteres."
msgstr[0] "Certifique-se de que seu texto tenha menos que %s caractere."
msgstr[1] "Certifique-se de que seu texto tenha menos que %s caracteres."
#: forms/__init__.py:385
msgid "Line breaks are not allowed here."
msgstr "Não são permitidas múltiplas linhas aqui."
msgstr "Não são permitidas quebras de linha aqui."
#: forms/__init__.py:480 forms/__init__.py:551 forms/__init__.py:589
#, python-format
@ -2037,7 +2038,7 @@ msgstr "sim,não,talvez"
#~ "\n"
#~ "%(text)s"
#~ msgstr ""
#~ "Este comentário foi envidao por um usuário que enviou menos de %(count)s "
#~ "Este comentário foi enviado por um usuário que enviou menos de %(count)s "
#~ "comentário:\n"
#~ "\n"
#~ "%(text)sEste comentário foi enviado por um usuário que enviou menos de %"
@ -2047,4 +2048,4 @@ msgstr "sim,não,talvez"
#, fuzzy
#~ msgid "count"
#~ msgstr "conteúdo"
#~ msgstr "contagem"

View File

@ -1,15 +1,15 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# Português do Brasil translation of django.
# Copyright (C) 2006 THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
# Carlos Eduardo de Paula <carlosedp@gmail.com>, 2006.
#
msgid ""
msgstr ""
"Project-Id-Version: django\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2005-12-09 11:51+0100\n"
"PO-Revision-Date: 2006-01-23 19:54-0200\n"
"Last-Translator: João Marcus Christ <joaoma@gmail.com>\n"
"PO-Revision-Date: 2006-11-01 17:45-0300\n"
"Last-Translator: Carlos Eduardo de Paula <carlosedp@gmail.com>\n"
"Language-Team: Português do Brasil <pt-br@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -51,7 +51,7 @@ msgid ""
"January February March April May June July August September October November "
"December"
msgstr ""
"Janeiro Fevereiro Março Abrio Maio Junho Julho Agosto Setembro Outubro Novembro "
"Janeiro Fevereiro Março Abril Maio Junho Julho Agosto Setembro Outubro Novembro "
"Dezembro"
#: contrib/admin/media/js/dateparse.js:27
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"

View File

@ -44,7 +44,7 @@ var DateTimeShortcuts = {
var shortcuts_span = document.createElement('span');
inp.parentNode.insertBefore(shortcuts_span, inp.nextSibling);
var now_link = document.createElement('a');
now_link.setAttribute('href', "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date().getHourMinute());");
now_link.setAttribute('href', "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date().getHourMinuteSecond());");
now_link.appendChild(document.createTextNode(gettext('Now')));
var clock_link = document.createElement('a');
clock_link.setAttribute('href', 'javascript:DateTimeShortcuts.openClock(' + num + ');');
@ -80,10 +80,10 @@ var DateTimeShortcuts = {
quickElement('h2', clock_box, gettext('Choose a time'));
time_list = quickElement('ul', clock_box, '');
time_list.className = 'timelist';
quickElement("a", quickElement("li", time_list, ""), gettext("Now"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date().getHourMinute());")
quickElement("a", quickElement("li", time_list, ""), gettext("Midnight"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", '00:00');")
quickElement("a", quickElement("li", time_list, ""), gettext("6 a.m."), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", '06:00');")
quickElement("a", quickElement("li", time_list, ""), gettext("Noon"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", '12:00');")
quickElement("a", quickElement("li", time_list, ""), gettext("Now"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date().getHourMinuteSecond());")
quickElement("a", quickElement("li", time_list, ""), gettext("Midnight"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", '00:00:00');")
quickElement("a", quickElement("li", time_list, ""), gettext("6 a.m."), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", '06:00:00');")
quickElement("a", quickElement("li", time_list, ""), gettext("Noon"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", '12:00:00');")
cancel_p = quickElement('p', clock_box, '');
cancel_p.className = 'calendar-cancel';

View File

@ -119,6 +119,10 @@ Date.prototype.getTwoDigitMinute = function() {
return (this.getMinutes() < 10) ? '0' + this.getMinutes() : this.getMinutes();
}
Date.prototype.getTwoDigitSecond = function() {
return (this.getSeconds() < 10) ? '0' + this.getSeconds() : this.getSeconds();
}
Date.prototype.getISODate = function() {
return this.getCorrectYear() + '-' + this.getTwoDigitMonth() + '-' + this.getTwoDigitDate();
}
@ -127,6 +131,10 @@ Date.prototype.getHourMinute = function() {
return this.getTwoDigitHour() + ':' + this.getTwoDigitMinute();
}
Date.prototype.getHourMinuteSecond = function() {
return this.getTwoDigitHour() + ':' + this.getTwoDigitMinute() + ':' + this.getTwoDigitSecond();
}
// ----------------------------------------------------------------------------
// String object extensions
// ----------------------------------------------------------------------------

View File

@ -169,8 +169,8 @@ var dateParsePatterns = [
handler: function(bits) {
var d = new Date();
d.setYear(parseInt(bits[1]));
d.setDate(parseInt(bits[3], 10));
d.setMonth(parseInt(bits[2], 10) - 1);
d.setDate(parseInt(bits[3], 10));
return d;
}
},

View File

@ -187,8 +187,8 @@ def output_all(form_fields):
output_all = register.simple_tag(output_all)
def auto_populated_field_script(auto_pop_fields, change = False):
t = []
for field in auto_pop_fields:
t = []
if change:
t.append('document.getElementById("id_%s")._changed = true;' % field.name)
else:

View File

@ -98,13 +98,13 @@ def view_index(request):
return missing_docutils_page(request)
if settings.ADMIN_FOR:
settings_modules = [__import__(m, '', '', ['']) for m in settings.ADMIN_FOR]
settings_modules = [__import__(m, {}, {}, ['']) for m in settings.ADMIN_FOR]
else:
settings_modules = [settings]
views = []
for settings_mod in settings_modules:
urlconf = __import__(settings_mod.ROOT_URLCONF, '', '', [''])
urlconf = __import__(settings_mod.ROOT_URLCONF, {}, {}, [''])
view_functions = extract_views_from_urlpatterns(urlconf.urlpatterns)
if Site._meta.installed:
site_obj = Site.objects.get(pk=settings_mod.SITE_ID)
@ -127,7 +127,7 @@ def view_detail(request, view):
mod, func = urlresolvers.get_mod_func(view)
try:
view_func = getattr(__import__(mod, '', '', ['']), func)
view_func = getattr(__import__(mod, {}, {}, ['']), func)
except (ImportError, AttributeError):
raise Http404
title, body, metadata = utils.parse_docstring(view_func.__doc__)
@ -235,7 +235,7 @@ model_detail = staff_member_required(model_detail)
def template_detail(request, template):
templates = []
for site_settings_module in settings.ADMIN_FOR:
settings_mod = __import__(site_settings_module, '', '', [''])
settings_mod = __import__(site_settings_module, {}, {}, [''])
if Site._meta.installed:
site_obj = Site.objects.get(pk=settings_mod.SITE_ID)
else:

View File

@ -14,7 +14,7 @@ def template_validator(request):
# get a dict of {site_id : settings_module} for the validator
settings_modules = {}
for mod in settings.ADMIN_FOR:
settings_module = __import__(mod, '', '', [''])
settings_module = __import__(mod, {}, {}, [''])
settings_modules[settings_module.SITE_ID] = settings_module
manipulator = TemplateValidator(settings_modules)
new_data, errors = {}, {}

View File

@ -9,7 +9,7 @@ def load_backend(path):
i = path.rfind('.')
module, attr = path[:i], path[i+1:]
try:
mod = __import__(module, '', '', [attr])
mod = __import__(module, {}, {}, [attr])
except ImportError, e:
raise ImproperlyConfigured, 'Error importing authentication backend %s: "%s"' % (module, e)
try:

View File

@ -34,7 +34,7 @@ class CommentManager(models.Manager):
"""
Given a rating_string, this returns a tuple of (rating_range, options).
>>> s = "scale:1-10|First_category|Second_category"
>>> get_rating_options(s)
>>> Comment.objects.get_rating_options(s)
([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], ['First category', 'Second category'])
"""
rating_range, options = rating_string.split('|', 1)

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.google.com/schemas/sitemap/0.84">
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
{% spaceless %}
{% for url in urlset %}
<url>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.google.com/schemas/sitemap/0.84">
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemapindex/0.9">
{% for location in sitemaps %}<sitemap><loc>{{ location|escape }}</loc></sitemap>{% endfor %}
</sitemapindex>

View File

@ -48,7 +48,7 @@ def get_cache(backend_uri):
if host.endswith('/'):
host = host[:-1]
cache_class = getattr(__import__('django.core.cache.backends.%s' % BACKENDS[scheme], '', '', ['']), 'CacheClass')
cache_class = getattr(__import__('django.core.cache.backends.%s' % BACKENDS[scheme], {}, {}, ['']), 'CacheClass')
return cache_class(host, params)
cache = get_cache(settings.CACHE_BACKEND)

View File

@ -26,7 +26,7 @@ class BaseHandler(object):
raise exceptions.ImproperlyConfigured, '%s isn\'t a middleware module' % middleware_path
mw_module, mw_classname = middleware_path[:dot], middleware_path[dot+1:]
try:
mod = __import__(mw_module, '', '', [''])
mod = __import__(mw_module, {}, {}, [''])
except ImportError, e:
raise exceptions.ImproperlyConfigured, 'Error importing middleware %s: "%s"' % (mw_module, e)
try:

View File

@ -157,7 +157,8 @@ class WSGIRequest(http.HttpRequest):
return self._raw_post_data
except AttributeError:
buf = StringIO()
content_length = int(self.environ['CONTENT_LENGTH'])
# CONTENT_LENGTH might be absent if POST doesn't have content at all (lighttpd)
content_length = int(self.environ.get('CONTENT_LENGTH', 0))
safe_copyfileobj(self.environ['wsgi.input'], buf, size=content_length)
self._raw_post_data = buf.getvalue()
buf.close()

View File

@ -4,6 +4,11 @@ from django.conf import settings
from email.MIMEText import MIMEText
from email.Header import Header
import smtplib, rfc822
import socket
import time
import random
DNS_NAME = socket.getfqdn() # Cache the hostname
class BadHeaderError(ValueError):
pass
@ -50,6 +55,11 @@ def send_mass_mail(datatuple, fail_silently=False, auth_user=settings.EMAIL_HOST
msg['From'] = from_email
msg['To'] = ', '.join(recipient_list)
msg['Date'] = rfc822.formatdate()
try:
random_bits = str(random.getrandbits(64))
except AttributeError: # Python 2.3 doesn't have random.getrandbits().
random_bits = ''.join([random.choice('1234567890') for i in range(19)])
msg['Message-ID'] = "<%d.%s@%s>" % (time.time(), random_bits, DNS_NAME)
try:
server.sendmail(from_email, recipient_list, msg.as_string())
num_sent += 1

View File

@ -32,6 +32,7 @@ class dummy: pass
style = dummy()
style.ERROR = termcolors.make_style(fg='red', opts=('bold',))
style.ERROR_OUTPUT = termcolors.make_style(fg='red', opts=('bold',))
style.NOTICE = termcolors.make_style(fg='red')
style.SQL_FIELD = termcolors.make_style(fg='green', opts=('bold',))
style.SQL_COLTYPE = termcolors.make_style(fg='green')
style.SQL_KEYWORD = termcolors.make_style(fg='yellow')
@ -348,6 +349,8 @@ def get_sql_initial_data_for_model(model):
if os.path.exists(sql_file):
fp = open(sql_file, 'U')
for statement in statements.split(fp.read()):
# Remove any comments from the file
statement = re.sub(r"--.*[\n\Z]", "", statement)
if statement.strip():
output.append(statement + ";")
fp.close()
@ -445,7 +448,7 @@ def syncdb(verbosity=1, interactive=True):
# dispatcher events.
for app_name in settings.INSTALLED_APPS:
try:
__import__(app_name + '.management', '', '', [''])
__import__(app_name + '.management', {}, {}, [''])
except ImportError:
pass
@ -696,7 +699,10 @@ def _start_helper(app_or_project, name, directory, other_name=''):
fp_new.write(fp_old.read().replace('{{ %s_name }}' % app_or_project, name).replace('{{ %s_name }}' % other, other_name))
fp_old.close()
fp_new.close()
shutil.copymode(path_old, path_new)
try:
shutil.copymode(path_old, path_new)
except OSError:
sys.stderr.write(style.NOTICE("Notice: Couldn't set permission bits on %s. You're probably using an uncommon filesystem setup. No problem.\n" % path_new))
def startproject(project_name, directory):
"Creates a Django project for the given project_name in the given directory."
@ -1226,7 +1232,7 @@ def test(app_labels, verbosity=1):
test_module_name = '.'.join(test_path[:-1])
else:
test_module_name = '.'
test_module = __import__(test_module_name, [],[],test_path[-1])
test_module = __import__(test_module_name, {}, {}, test_path[-1])
test_runner = getattr(test_module, test_path[-1])
test_runner(app_list, verbosity)
@ -1415,7 +1421,7 @@ def setup_environ(settings_mod):
project_directory = os.path.dirname(settings_mod.__file__)
project_name = os.path.basename(project_directory)
sys.path.append(os.path.join(project_directory, '..'))
project_module = __import__(project_name, '', '', [''])
project_module = __import__(project_name, {}, {}, [''])
sys.path.pop()
# Set DJANGO_SETTINGS_MODULE appropriately.

View File

@ -1,54 +1,46 @@
from math import ceil
class InvalidPage(Exception):
pass
class ObjectPaginator(object):
"""
This class makes pagination easy. Feed it a QuerySet, plus the number of
objects you want on each page. Then read the hits and pages properties to
This class makes pagination easy. Feed it a QuerySet or list, plus the number
of objects you want on each page. Then read the hits and pages properties to
see how many pages it involves. Call get_page with a page number (starting
at 0) to get back a list of objects for that page.
Finally, check if a page number has a next/prev page using
has_next_page(page_number) and has_previous_page(page_number).
Use orphans to avoid small final pages. For example:
13 records, num_per_page=10, orphans=2 --> pages==2, len(self.get_page(0))==10
12 records, num_per_page=10, orphans=2 --> pages==1, len(self.get_page(0))==12
"""
def __init__(self, query_set, num_per_page):
def __init__(self, query_set, num_per_page, orphans=0):
self.query_set = query_set
self.num_per_page = num_per_page
self._hits, self._pages = None, None
self._has_next = {} # Caches page_number -> has_next_boolean
self.orphans = orphans
self._hits = self._pages = None
def get_page(self, page_number):
def validate_page_number(self, page_number):
try:
page_number = int(page_number)
except ValueError:
raise InvalidPage
if page_number < 0:
if page_number < 0 or page_number > self.pages - 1:
raise InvalidPage
return page_number
# Retrieve one extra record, and check for the existence of that extra
# record to determine whether there's a next page.
limit = self.num_per_page + 1
offset = page_number * self.num_per_page
object_list = list(self.query_set[offset:offset+limit])
if not object_list:
raise InvalidPage
self._has_next[page_number] = (len(object_list) > self.num_per_page)
return object_list[:self.num_per_page]
def get_page(self, page_number):
page_number = self.validate_page_number(page_number)
bottom = page_number * self.num_per_page
top = bottom + self.num_per_page
if top + self.orphans >= self.hits:
top = self.hits
return self.query_set[bottom:top]
def has_next_page(self, page_number):
"Does page $page_number have a 'next' page?"
if not self._has_next.has_key(page_number):
if self._pages is None:
offset = (page_number + 1) * self.num_per_page
self._has_next[page_number] = len(self.query_set[offset:offset+1]) > 0
else:
self._has_next[page_number] = page_number < (self.pages - 1)
return self._has_next[page_number]
return page_number < self.pages - 1
def has_previous_page(self, page_number):
return page_number > 0
@ -58,8 +50,7 @@ class ObjectPaginator(object):
Returns the 1-based index of the first object on the given page,
relative to total objects found (hits).
"""
if page_number == 0:
return 1
page_number = self.validate_page_number(page_number)
return (self.num_per_page * page_number) + 1
def last_on_page(self, page_number):
@ -67,20 +58,30 @@ class ObjectPaginator(object):
Returns the 1-based index of the last object on the given page,
relative to total objects found (hits).
"""
if page_number == 0 and self.num_per_page >= self._hits:
return self._hits
elif page_number == (self._pages - 1) and (page_number + 1) * self.num_per_page > self._hits:
return self._hits
return (page_number + 1) * self.num_per_page
page_number = self.validate_page_number(page_number)
page_number += 1 # 1-base
if page_number == self.pages:
return self.hits
return page_number * self.num_per_page
def _get_hits(self):
if self._hits is None:
self._hits = self.query_set.count()
# Try .count() or fall back to len().
try:
self._hits = int(self.query_set.count())
except (AttributeError, TypeError, ValueError):
# AttributeError if query_set has no object count.
# TypeError if query_set.count() required arguments.
# ValueError if int() fails.
self._hits = len(self.query_set)
return self._hits
def _get_pages(self):
if self._pages is None:
self._pages = int(ceil(self.hits / float(self.num_per_page)))
hits = (self.hits - 1 - self.orphans)
if hits < 1:
hits = 0
self._pages = hits // self.num_per_page + 1
return self._pages
hits = property(_get_hits)

View File

@ -29,7 +29,7 @@ _serializers = {}
def register_serializer(format, serializer_module):
"""Register a new serializer by passing in a module name."""
module = __import__(serializer_module, '', '', [''])
module = __import__(serializer_module, {}, {}, [''])
_serializers[format] = module
def unregister_serializer(format):

View File

@ -28,6 +28,7 @@ class Serializer(object):
self.options = options
self.stream = options.get("stream", StringIO())
self.selected_fields = options.get("fields")
self.start_serialization()
for obj in queryset:
@ -36,11 +37,14 @@ class Serializer(object):
if field is obj._meta.pk:
continue
elif field.rel is None:
self.handle_field(obj, field)
if self.selected_fields is None or field.attname in self.selected_fields:
self.handle_field(obj, field)
else:
self.handle_fk_field(obj, field)
if self.selected_fields is None or field.attname[:-3] in self.selected_fields:
self.handle_fk_field(obj, field)
for field in obj._meta.many_to_many:
self.handle_m2m_field(obj, field)
if self.selected_fields is None or field.attname in self.selected_fields:
self.handle_m2m_field(obj, field)
self.end_object(obj)
self.end_serialization()
return self.getvalue()

View File

@ -76,7 +76,7 @@ def Deserializer(object_list, **options):
m2m_data[field.name] = field.rel.to._default_manager.in_bulk(field_value).values()
# Handle FK fields
elif field.rel and isinstance(field.rel, models.ManyToOneRel):
elif field.rel and isinstance(field.rel, models.ManyToOneRel) and field_value is not None:
try:
data[field.name] = field.rel.to._default_manager.get(pk=field_value)
except field.rel.to.DoesNotExist:

View File

@ -166,7 +166,11 @@ class Deserializer(base.Deserializer):
# If it doesn't exist, set the field to None (which might trigger
# validation error, but that's expected).
RelatedModel = self._get_model_from_node(node, "to")
return RelatedModel.objects.get(pk=getInnerText(node).strip().encode(self.encoding))
# Check if there is a child node named 'None', returning None if so.
if len(node.childNodes) == 1 and node.childNodes[0].nodeName == 'None':
return None
else:
return RelatedModel.objects.get(pk=getInnerText(node).strip().encode(self.encoding))
def _handle_m2m_field_node(self, node):
"""

View File

@ -31,9 +31,11 @@ Optional Fcgi settings: (setting=value)
port=PORTNUM port to listen on.
socket=FILE UNIX socket to listen on.
method=IMPL prefork or threaded (default prefork)
maxspare=NUMBER max number of spare processes to keep running.
minspare=NUMBER min number of spare processes to prefork.
maxchildren=NUMBER hard limit number of processes in prefork mode.
maxrequests=NUMBER number of requests a child handles before it is
killed and a new child is forked (0 = no limit).
maxspare=NUMBER max number of spare processes / threads
minspare=NUMBER min number of spare processes / threads.
maxchildren=NUMBER hard limit number of processes / threads
daemonize=BOOL whether to detach from terminal.
pidfile=FILE write the spawned process-id to this file.
workdir=DIRECTORY change to this directory when daemonizing
@ -66,6 +68,7 @@ FASTCGI_OPTIONS = {
'maxspare': 5,
'minspare': 2,
'maxchildren': 50,
'maxrequests': 0,
}
def fastcgi_help(message=None):
@ -103,10 +106,15 @@ def runfastcgi(argset=[], **kwargs):
'maxSpare': int(options["maxspare"]),
'minSpare': int(options["minspare"]),
'maxChildren': int(options["maxchildren"]),
'maxRequests': int(options["maxrequests"]),
}
elif options['method'] in ('thread', 'threaded'):
from flup.server.fcgi import WSGIServer
wsgi_opts = {}
wsgi_opts = {
'maxSpare': int(options["maxspare"]),
'minSpare': int(options["minspare"]),
'maxThreads': int(options["maxchildren"]),
}
else:
return fastcgi_help("ERROR: Implementation must be one of prefork or thread.")

View File

@ -21,7 +21,10 @@ class NoReverseMatch(Exception):
def get_mod_func(callback):
# Converts 'django.views.news.stories.story_detail' to
# ['django.views.news.stories', 'story_detail']
dot = callback.rindex('.')
try:
dot = callback.rindex('.')
except ValueError:
return callback, ''
return callback[:dot], callback[dot+1:]
def reverse_helper(regex, *args, **kwargs):
@ -119,7 +122,7 @@ class RegexURLPattern(object):
return self._callback
mod_name, func_name = get_mod_func(self._callback_str)
try:
self._callback = getattr(__import__(mod_name, '', '', ['']), func_name)
self._callback = getattr(__import__(mod_name, {}, {}, ['']), func_name)
except ImportError, e:
raise ViewDoesNotExist, "Could not import %s. Error was: %s" % (mod_name, str(e))
except AttributeError, e:
@ -130,7 +133,7 @@ class RegexURLPattern(object):
def reverse(self, viewname, *args, **kwargs):
mod_name, func_name = get_mod_func(viewname)
try:
lookup_view = getattr(__import__(mod_name, '', '', ['']), func_name)
lookup_view = getattr(__import__(mod_name, {}, {}, ['']), func_name)
except (ImportError, AttributeError):
raise NoReverseMatch
if lookup_view != self.callback:
@ -171,7 +174,7 @@ class RegexURLResolver(object):
return self._urlconf_module
except AttributeError:
try:
self._urlconf_module = __import__(self.urlconf_name, '', '', [''])
self._urlconf_module = __import__(self.urlconf_name, {}, {}, [''])
except ValueError, e:
# Invalid urlconf_name, such as "foo.bar." (note trailing period)
raise ImproperlyConfigured, "Error while importing URLconf %r: %s" % (self.urlconf_name, e)
@ -186,7 +189,7 @@ class RegexURLResolver(object):
callback = getattr(self.urlconf_module, 'handler%s' % view_type)
mod_name, func_name = get_mod_func(callback)
try:
return getattr(__import__(mod_name, '', '', ['']), func_name), {}
return getattr(__import__(mod_name, {}, {}, ['']), func_name), {}
except (ImportError, AttributeError), e:
raise ViewDoesNotExist, "Tried %s. Error was: %s" % (callback, str(e))
@ -200,7 +203,7 @@ class RegexURLResolver(object):
if not callable(lookup_view):
mod_name, func_name = get_mod_func(lookup_view)
try:
lookup_view = getattr(__import__(mod_name, '', '', ['']), func_name)
lookup_view = getattr(__import__(mod_name, {}, {}, ['']), func_name)
except (ImportError, AttributeError):
raise NoReverseMatch
for pattern in self.urlconf_module.urlpatterns:

View File

@ -8,6 +8,7 @@ validator will *always* be run, regardless of whether its associated
form field is required.
"""
import urllib2
from django.conf import settings
from django.utils.translation import gettext, gettext_lazy, ngettext
from django.utils.functional import Promise, lazy
@ -223,18 +224,26 @@ def isWellFormedXmlFragment(field_data, all_data):
isWellFormedXml('<root>%s</root>' % field_data, all_data)
def isExistingURL(field_data, all_data):
import urllib2
try:
u = urllib2.urlopen(field_data)
headers = {
"Accept" : "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5",
"Accept-Language" : "en-us,en;q=0.5",
"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7",
"Connection" : "close",
"User-Agent": settings.URL_VALIDATOR_USER_AGENT
}
req = urllib2.Request(field_data,None, headers)
u = urllib2.urlopen(req)
except ValueError:
raise ValidationError, gettext("Invalid URL: %s") % field_data
raise ValidationError, _("Invalid URL: %s") % field_data
except urllib2.HTTPError, e:
# 401s are valid; they just mean authorization is required.
if e.code not in ('401',):
raise ValidationError, gettext("The URL %s is a broken link.") % field_data
# 301 and 302 are redirects; they just mean look somewhere else.
if str(e.code) not in ('401','301','302'):
raise ValidationError, _("The URL %s is a broken link.") % field_data
except: # urllib2.URLError, httplib.InvalidURL, etc.
raise ValidationError, gettext("The URL %s is a broken link.") % field_data
raise ValidationError, _("The URL %s is a broken link.") % field_data
def isValidUSState(field_data, all_data):
"Checks that the given string is a valid two-letter U.S. state abbreviation"
states = ['AA', 'AE', 'AK', 'AL', 'AP', 'AR', 'AS', 'AZ', 'CA', 'CO', 'CT', 'DC', 'DE', 'FL', 'FM', 'GA', 'GU', 'HI', 'IA', 'ID', 'IL', 'IN', 'KS', 'KY', 'LA', 'MA', 'MD', 'ME', 'MH', 'MI', 'MN', 'MO', 'MP', 'MS', 'MT', 'NC', 'ND', 'NE', 'NH', 'NJ', 'NM', 'NV', 'NY', 'OH', 'OK', 'OR', 'PA', 'PR', 'PW', 'RI', 'SC', 'SD', 'TN', 'TX', 'UT', 'VA', 'VI', 'VT', 'WA', 'WI', 'WV', 'WY']
@ -344,6 +353,38 @@ class UniqueAmongstFieldsWithPrefix(object):
if field_name != self.field_name and value == field_data:
raise ValidationError, self.error_message
class NumberIsInRange(object):
"""
Validator that tests if a value is in a range (inclusive).
"""
def __init__(self, lower=None, upper=None, error_message=''):
self.lower, self.upper = lower, upper
if not error_message:
if lower and upper:
self.error_message = gettext("This value must be between %s and %s.") % (lower, upper)
elif lower:
self.error_message = gettext("This value must be at least %s.") % lower
elif upper:
self.error_message = gettext("This value must be no more than %s.") % upper
else:
self.error_message = error_message
def __call__(self, field_data, all_data):
# Try to make the value numeric. If this fails, we assume another
# validator will catch the problem.
try:
val = float(field_data)
except ValueError:
return
# Now validate
if self.lower and self.upper and (val < self.lower or val > self.upper):
raise ValidationError(self.error_message)
elif self.lower and val < self.lower:
raise ValidationError(self.error_message)
elif self.upper and val > self.upper:
raise ValidationError(self.error_message)
class IsAPowerOf(object):
"""
>>> v = IsAPowerOf(2)

View File

@ -17,6 +17,6 @@ def populate_xheaders(request, response, model, object_id):
or if the request is from a logged in staff member.
"""
from django.conf import settings
if request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS or (request.user.is_authenticated() and request.user.is_staff):
if request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS or (hasattr(request, 'user') and request.user.is_authenticated() and request.user.is_staff):
response['X-Object-Type'] = "%s.%s" % (model._meta.app_label, model._meta.object_name.lower())
response['X-Object-Id'] = str(object_id)

View File

@ -8,7 +8,7 @@ if not settings.DATABASE_ENGINE:
settings.DATABASE_ENGINE = 'dummy'
try:
backend = __import__('django.db.backends.%s.base' % settings.DATABASE_ENGINE, '', '', [''])
backend = __import__('django.db.backends.%s.base' % settings.DATABASE_ENGINE, {}, {}, [''])
except ImportError, e:
# The database backend wasn't found. Display a helpful error message
# listing all possible database backends.
@ -18,16 +18,16 @@ except ImportError, e:
available_backends = [f for f in os.listdir(backend_dir) if not f.startswith('_') and not f.startswith('.') and not f.endswith('.py') and not f.endswith('.pyc')]
available_backends.sort()
if settings.DATABASE_ENGINE not in available_backends:
raise ImproperlyConfigured, "%r isn't an available database backend. vailable options are: %s" % \
raise ImproperlyConfigured, "%r isn't an available database backend. Available options are: %s" % \
(settings.DATABASE_ENGINE, ", ".join(map(repr, available_backends)))
else:
raise # If there's some other error, this must be an error in Django itself.
get_introspection_module = lambda: __import__('django.db.backends.%s.introspection' % settings.DATABASE_ENGINE, '', '', [''])
get_creation_module = lambda: __import__('django.db.backends.%s.creation' % settings.DATABASE_ENGINE, '', '', [''])
runshell = lambda: __import__('django.db.backends.%s.client' % settings.DATABASE_ENGINE, '', '', ['']).runshell()
get_introspection_module = lambda: __import__('django.db.backends.%s.introspection' % settings.DATABASE_ENGINE, {}, {}, [''])
get_creation_module = lambda: __import__('django.db.backends.%s.creation' % settings.DATABASE_ENGINE, {}, {}, [''])
runshell = lambda: __import__('django.db.backends.%s.client' % settings.DATABASE_ENGINE, {}, {}, ['']).runshell()
connection = backend.DatabaseWrapper()
connection = backend.DatabaseWrapper(**settings.DATABASE_OPTIONS)
DatabaseError = backend.DatabaseError
# Register an event that closes the database connection

View File

@ -55,7 +55,7 @@ except ImportError:
from django.utils._threading_local import local
class DatabaseWrapper(local):
def __init__(self):
def __init__(self, **kwargs):
self.connection = None
self.queries = []

View File

@ -20,6 +20,9 @@ class DatabaseWrapper:
_commit = complain
_rollback = complain
def __init__(self, **kwargs):
pass
def close(self):
pass # close()

View File

@ -65,10 +65,11 @@ except ImportError:
from django.utils._threading_local import local
class DatabaseWrapper(local):
def __init__(self):
def __init__(self, **kwargs):
self.connection = None
self.queries = []
self.server_version = None
self.options = kwargs
def _valid_connection(self):
if self.connection is not None:
@ -95,6 +96,7 @@ class DatabaseWrapper(local):
kwargs['host'] = settings.DATABASE_HOST
if settings.DATABASE_PORT:
kwargs['port'] = int(settings.DATABASE_PORT)
kwargs.update(self.options)
self.connection = Database.connect(**kwargs)
cursor = self.connection.cursor()
if self.connection.get_server_info() >= '4.1':

View File

@ -21,9 +21,10 @@ except ImportError:
from django.utils._threading_local import local
class DatabaseWrapper(local):
def __init__(self):
def __init__(self, **kwargs):
self.connection = None
self.queries = []
self.options = kwargs
def _valid_connection(self):
return self.connection is not None
@ -35,10 +36,10 @@ class DatabaseWrapper(local):
settings.DATABASE_HOST = 'localhost'
if len(settings.DATABASE_PORT.strip()) != 0:
dsn = Database.makedsn(settings.DATABASE_HOST, int(settings.DATABASE_PORT), settings.DATABASE_NAME)
self.connection = Database.connect(settings.DATABASE_USER, settings.DATABASE_PASSWORD, dsn)
self.connection = Database.connect(settings.DATABASE_USER, settings.DATABASE_PASSWORD, dsn, **self.options)
else:
conn_string = "%s/%s@%s" % (settings.DATABASE_USER, settings.DATABASE_PASSWORD, settings.DATABASE_NAME)
self.connection = Database.connect(conn_string)
self.connection = Database.connect(conn_string, **self.options)
return FormatStylePlaceholderCursor(self.connection)
def _commit(self):

View File

@ -21,9 +21,10 @@ except ImportError:
from django.utils._threading_local import local
class DatabaseWrapper(local):
def __init__(self):
def __init__(self, **kwargs):
self.connection = None
self.queries = []
self.options = kwargs
def cursor(self):
from django.conf import settings
@ -40,7 +41,7 @@ class DatabaseWrapper(local):
conn_string += " host=%s" % settings.DATABASE_HOST
if settings.DATABASE_PORT:
conn_string += " port=%s" % settings.DATABASE_PORT
self.connection = Database.connect(conn_string)
self.connection = Database.connect(conn_string, **self.options)
self.connection.set_isolation_level(1) # make transactions transparent to all cursors
cursor = self.connection.cursor()
cursor.execute("SET TIME ZONE %s", [settings.TIME_ZONE])

View File

@ -21,9 +21,10 @@ except ImportError:
from django.utils._threading_local import local
class DatabaseWrapper(local):
def __init__(self):
def __init__(self, **kwargs):
self.connection = None
self.queries = []
self.options = kwargs
def cursor(self):
from django.conf import settings
@ -40,7 +41,7 @@ class DatabaseWrapper(local):
conn_string += " host=%s" % settings.DATABASE_HOST
if settings.DATABASE_PORT:
conn_string += " port=%s" % settings.DATABASE_PORT
self.connection = Database.connect(conn_string)
self.connection = Database.connect(conn_string, **self.options)
self.connection.set_isolation_level(1) # make transactions transparent to all cursors
cursor = self.connection.cursor()
cursor.tzinfo_factory = None

View File

@ -42,16 +42,20 @@ except ImportError:
from django.utils._threading_local import local
class DatabaseWrapper(local):
def __init__(self):
def __init__(self, **kwargs):
self.connection = None
self.queries = []
self.options = kwargs
def cursor(self):
from django.conf import settings
if self.connection is None:
self.connection = Database.connect(settings.DATABASE_NAME,
detect_types=Database.PARSE_DECLTYPES | Database.PARSE_COLNAMES)
kwargs = {
'database': settings.DATABASE_NAME,
'detect_types': Database.PARSE_DECLTYPES | Database.PARSE_COLNAMES,
}
kwargs.update(self.options)
self.connection = Database.connect(**kwargs)
# Register extract and date_trunc functions.
self.connection.create_function("django_extract", 2, _sqlite_extract)
self.connection.create_function("django_date_trunc", 2, _sqlite_date_trunc)

View File

@ -17,7 +17,7 @@ class CursorDebugWrapper(object):
if not isinstance(params, (tuple, dict)):
params = tuple(params)
self.db.queries.append({
'sql': sql % tuple(params),
'sql': sql % params,
'time': "%.3f" % (stop - start),
})

View File

@ -381,24 +381,6 @@ class Model(object):
setattr(self, cachename, get_image_dimensions(filename))
return getattr(self, cachename)
# Handles setting many-to-many related objects.
# Example: Album.set_songs()
def _set_related_many_to_many(self, rel_class, rel_field, id_list):
id_list = map(int, id_list) # normalize to integers
rel = rel_field.rel.to
m2m_table = rel_field.m2m_db_table()
this_id = self._get_pk_val()
cursor = connection.cursor()
cursor.execute("DELETE FROM %s WHERE %s = %%s" % \
(backend.quote_name(m2m_table),
backend.quote_name(rel_field.m2m_column_name())), [this_id])
sql = "INSERT INTO %s (%s, %s) VALUES (%%s, %%s)" % \
(backend.quote_name(m2m_table),
backend.quote_name(rel_field.m2m_column_name()),
backend.quote_name(rel_field.m2m_reverse_name()))
cursor.executemany(sql, [(this_id, i) for i in id_list])
transaction.commit_unless_managed()
############################################
# HELPER FUNCTIONS (CURRIED MODEL METHODS) #
############################################

View File

@ -457,7 +457,9 @@ class DateField(Field):
def get_db_prep_save(self, value):
# Casts dates into string format for entry into database.
if value is not None:
if isinstance(value, datetime.datetime):
value = value.date().strftime('%Y-%m-%d')
elif isinstance(value, datetime.date):
value = value.strftime('%Y-%m-%d')
return Field.get_db_prep_save(self, value)
@ -487,12 +489,19 @@ class DateTimeField(DateField):
def get_db_prep_save(self, value):
# Casts dates into string format for entry into database.
if value is not None:
if isinstance(value, datetime.datetime):
# MySQL will throw a warning if microseconds are given, because it
# doesn't support microseconds.
if settings.DATABASE_ENGINE == 'mysql' and hasattr(value, 'microsecond'):
value = value.replace(microsecond=0)
value = str(value)
elif isinstance(value, datetime.date):
# MySQL will throw a warning if microseconds are given, because it
# doesn't support microseconds.
if settings.DATABASE_ENGINE == 'mysql' and hasattr(value, 'microsecond'):
value = datetime.datetime(value.year, value.month, value.day, microsecond=0)
value = str(value)
return Field.get_db_prep_save(self, value)
def get_db_prep_lookup(self, lookup_type, value):
@ -576,7 +585,7 @@ class FileField(Field):
# If the raw path is passed in, validate it's under the MEDIA_ROOT.
def isWithinMediaRoot(field_data, all_data):
f = os.path.abspath(os.path.join(settings.MEDIA_ROOT, field_data))
if not f.startswith(os.path.normpath(settings.MEDIA_ROOT)):
if not f.startswith(os.path.abspath(os.path.normpath(settings.MEDIA_ROOT))):
raise validators.ValidationError, _("Enter a valid filename.")
field_list[1].validator_list.append(isWithinMediaRoot)
return field_list

View File

@ -48,7 +48,7 @@ def get_app(app_label, emptyOK=False):
def load_app(app_name):
"Loads the app with the provided fully qualified name, and returns the model module."
global _app_list
mod = __import__(app_name, '', '', ['models'])
mod = __import__(app_name, {}, {}, ['models'])
if not hasattr(mod, 'models'):
return None
if mod.models not in _app_list:

View File

@ -292,7 +292,7 @@ def manipulator_validator_unique_together(field_name_list, opts, self, field_dat
# This is really not going to work for fields that have different
# form fields, e.g. DateTime.
# This validation needs to occur after html2python to be effective.
field_val = all_data.get(f.attname, None)
field_val = all_data.get(f.name, None)
if field_val is None:
# This will be caught by another validator, assuming the field
# doesn't have blank=True.
@ -309,7 +309,7 @@ def manipulator_validator_unique_together(field_name_list, opts, self, field_dat
pass
else:
raise validators.ValidationError, _("%(object)s with this %(type)s already exists for the given %(field)s.") % \
{'object': capfirst(opts.verbose_name), 'type': field_list[0].verbose_name, 'field': get_text_list([f.verbose_name for f in field_list[1:]], 'and')}
{'object': capfirst(opts.verbose_name), 'type': field_list[0].verbose_name, 'field': get_text_list([f.verbose_name for f in field_list[1:]], _('and'))}
def manipulator_validator_unique_for_date(from_field, date_field, opts, lookup_type, self, field_data, all_data):
from django.db.models.fields.related import ManyToOneRel

View File

@ -108,8 +108,13 @@ class FormWrapper(object):
This allows dictionary-style lookups of formfields. It also handles feeding
prepopulated data and validation error messages to the formfield objects.
"""
def __init__(self, manipulator, data, error_dict, edit_inline=True):
self.manipulator, self.data = manipulator, data
def __init__(self, manipulator, data=None, error_dict=None, edit_inline=True):
self.manipulator = manipulator
if data is None:
data = {}
if error_dict is None:
error_dict = {}
self.data = data
self.error_dict = error_dict
self._inline_collections = None
self.edit_inline = edit_inline

View File

@ -25,4 +25,5 @@ class GZipMiddleware(object):
response.content = compress_string(response.content)
response['Content-Encoding'] = 'gzip'
response['Content-Length'] = str(len(response.content))
return response

View File

@ -0,0 +1,28 @@
"""
Django validation and HTML form handling.
TODO:
Default value for field
Field labels
Nestable Forms
FatalValidationError -- short-circuits all other validators on a form
ValidationWarning
"This form field requires foo.js" and form.js_includes()
"""
from util import ValidationError
from widgets import *
from fields import *
from forms import Form
##########################
# DATABASE API SHORTCUTS #
##########################
def form_for_model(model):
"Returns a Form instance for the given Django model class."
raise NotImplementedError
def form_for_fields(field_list):
"Returns a Form instance for the given list of Django database field instances."
raise NotImplementedError

290
django/newforms/fields.py Normal file
View File

@ -0,0 +1,290 @@
"""
Field classes
"""
from util import ValidationError, DEFAULT_ENCODING, smart_unicode
from widgets import TextInput, CheckboxInput, Select, SelectMultiple
import datetime
import re
import time
__all__ = (
'Field', 'CharField', 'IntegerField',
'DEFAULT_DATE_INPUT_FORMATS', 'DateField',
'DEFAULT_DATETIME_INPUT_FORMATS', 'DateTimeField',
'RegexField', 'EmailField', 'URLField', 'BooleanField',
'ChoiceField', 'MultipleChoiceField',
'ComboField',
)
# These values, if given to to_python(), will trigger the self.required check.
EMPTY_VALUES = (None, '')
try:
set # Only available in Python 2.4+
except NameError:
from sets import Set as set # Python 2.3 fallback
class Field(object):
widget = TextInput # Default widget to use when rendering this type of Field.
# Tracks each time a Field instance is created. Used to retain order.
creation_counter = 0
def __init__(self, required=True, widget=None):
self.required = required
widget = widget or self.widget
if isinstance(widget, type):
widget = widget()
self.widget = widget
# Increase the creation counter, and save our local copy.
self.creation_counter = Field.creation_counter
Field.creation_counter += 1
def clean(self, value):
"""
Validates the given value and returns its "cleaned" value as an
appropriate Python object.
Raises ValidationError for any errors.
"""
if self.required and value in EMPTY_VALUES:
raise ValidationError(u'This field is required.')
return value
class CharField(Field):
def __init__(self, max_length=None, min_length=None, required=True, widget=None):
Field.__init__(self, required, widget)
self.max_length, self.min_length = max_length, min_length
def clean(self, value):
"Validates max_length and min_length. Returns a Unicode object."
Field.clean(self, value)
if value in EMPTY_VALUES: value = u''
value = smart_unicode(value)
if self.max_length is not None and len(value) > self.max_length:
raise ValidationError(u'Ensure this value has at most %d characters.' % self.max_length)
if self.min_length is not None and len(value) < self.min_length:
raise ValidationError(u'Ensure this value has at least %d characters.' % self.min_length)
return value
class IntegerField(Field):
def clean(self, value):
"""
Validates that int() can be called on the input. Returns the result
of int().
"""
super(IntegerField, self).clean(value)
try:
return int(value)
except (ValueError, TypeError):
raise ValidationError(u'Enter a whole number.')
DEFAULT_DATE_INPUT_FORMATS = (
'%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', # '2006-10-25', '10/25/2006', '10/25/06'
'%b %d %Y', '%b %d, %Y', # 'Oct 25 2006', 'Oct 25, 2006'
'%d %b %Y', '%d %b, %Y', # '25 Oct 2006', '25 Oct, 2006'
'%B %d %Y', '%B %d, %Y', # 'October 25 2006', 'October 25, 2006'
'%d %B %Y', '%d %B, %Y', # '25 October 2006', '25 October, 2006'
)
class DateField(Field):
def __init__(self, input_formats=None, required=True, widget=None):
Field.__init__(self, required, widget)
self.input_formats = input_formats or DEFAULT_DATE_INPUT_FORMATS
def clean(self, value):
"""
Validates that the input can be converted to a date. Returns a Python
datetime.date object.
"""
Field.clean(self, value)
if value in EMPTY_VALUES:
return None
if isinstance(value, datetime.datetime):
return value.date()
if isinstance(value, datetime.date):
return value
for format in self.input_formats:
try:
return datetime.date(*time.strptime(value, format)[:3])
except ValueError:
continue
raise ValidationError(u'Enter a valid date.')
DEFAULT_DATETIME_INPUT_FORMATS = (
'%Y-%m-%d %H:%M:%S', # '2006-10-25 14:30:59'
'%Y-%m-%d %H:%M', # '2006-10-25 14:30'
'%Y-%m-%d', # '2006-10-25'
'%m/%d/%Y %H:%M:%S', # '10/25/2006 14:30:59'
'%m/%d/%Y %H:%M', # '10/25/2006 14:30'
'%m/%d/%Y', # '10/25/2006'
'%m/%d/%y %H:%M:%S', # '10/25/06 14:30:59'
'%m/%d/%y %H:%M', # '10/25/06 14:30'
'%m/%d/%y', # '10/25/06'
)
class DateTimeField(Field):
def __init__(self, input_formats=None, required=True, widget=None):
Field.__init__(self, required, widget)
self.input_formats = input_formats or DEFAULT_DATETIME_INPUT_FORMATS
def clean(self, value):
"""
Validates that the input can be converted to a datetime. Returns a
Python datetime.datetime object.
"""
Field.clean(self, value)
if value in EMPTY_VALUES:
return None
if isinstance(value, datetime.datetime):
return value
if isinstance(value, datetime.date):
return datetime.datetime(value.year, value.month, value.day)
for format in self.input_formats:
try:
return datetime.datetime(*time.strptime(value, format)[:6])
except ValueError:
continue
raise ValidationError(u'Enter a valid date/time.')
class RegexField(Field):
def __init__(self, regex, error_message=None, required=True, widget=None):
"""
regex can be either a string or a compiled regular expression object.
error_message is an optional error message to use, if
'Enter a valid value' is too generic for you.
"""
Field.__init__(self, required, widget)
if isinstance(regex, basestring):
regex = re.compile(regex)
self.regex = regex
self.error_message = error_message or u'Enter a valid value.'
def clean(self, value):
"""
Validates that the input matches the regular expression. Returns a
Unicode object.
"""
Field.clean(self, value)
if value in EMPTY_VALUES: value = u''
value = smart_unicode(value)
if not self.regex.search(value):
raise ValidationError(self.error_message)
return value
email_re = re.compile(
r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*" # dot-atom
r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-011\013\014\016-\177])*"' # quoted-string
r')@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}$', re.IGNORECASE) # domain
class EmailField(RegexField):
def __init__(self, required=True, widget=None):
RegexField.__init__(self, email_re, u'Enter a valid e-mail address.', required, widget)
url_re = re.compile(
r'^https?://' # http:// or https://
r'(?:[A-Z0-9-]+\.)+[A-Z]{2,6}' # domain
r'(?::\d+)?' # optional port
r'(?:/?|/\S+)$', re.IGNORECASE)
try:
from django.conf import settings
URL_VALIDATOR_USER_AGENT = settings.URL_VALIDATOR_USER_AGENT
except ImportError:
# It's OK if Django settings aren't configured.
URL_VALIDATOR_USER_AGENT = 'Django (http://www.djangoproject.com/)'
class URLField(RegexField):
def __init__(self, required=True, verify_exists=False, widget=None,
validator_user_agent=URL_VALIDATOR_USER_AGENT):
RegexField.__init__(self, url_re, u'Enter a valid URL.', required, widget)
self.verify_exists = verify_exists
self.user_agent = validator_user_agent
def clean(self, value):
value = RegexField.clean(self, value)
if self.verify_exists:
import urllib2
from django.conf import settings
headers = {
"Accept": "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5",
"Accept-Language": "en-us,en;q=0.5",
"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7",
"Connection": "close",
"User-Agent": self.user_agent,
}
try:
req = urllib2.Request(value, None, headers)
u = urllib2.urlopen(req)
except ValueError:
raise ValidationError(u'Enter a valid URL.')
except: # urllib2.URLError, httplib.InvalidURL, etc.
raise ValidationError(u'This URL appears to be a broken link.')
return value
class BooleanField(Field):
widget = CheckboxInput
def clean(self, value):
"Returns a Python boolean object."
Field.clean(self, value)
return bool(value)
class ChoiceField(Field):
def __init__(self, choices=(), required=True, widget=Select):
if isinstance(widget, type):
widget = widget(choices=choices)
Field.__init__(self, required, widget)
self.choices = choices
def clean(self, value):
"""
Validates that the input is in self.choices.
"""
value = Field.clean(self, value)
if value in EMPTY_VALUES: value = u''
value = smart_unicode(value)
valid_values = set([str(k) for k, v in self.choices])
if value not in valid_values:
raise ValidationError(u'Select a valid choice. %s is not one of the available choices.' % value)
return value
class MultipleChoiceField(ChoiceField):
def __init__(self, choices=(), required=True, widget=SelectMultiple):
ChoiceField.__init__(self, choices, required, widget)
def clean(self, value):
"""
Validates that the input is a list or tuple.
"""
if not isinstance(value, (list, tuple)):
raise ValidationError(u'Enter a list of values.')
if self.required and not value:
raise ValidationError(u'This field is required.')
new_value = []
for val in value:
val = smart_unicode(val)
new_value.append(val)
# Validate that each value in the value list is in self.choices.
valid_values = set([k for k, v in self.choices])
for val in new_value:
if val not in valid_values:
raise ValidationError(u'Select a valid choice. %s is not one of the available choices.' % val)
return new_value
class ComboField(Field):
def __init__(self, fields=(), required=True, widget=None):
Field.__init__(self, required, widget)
self.fields = fields
def clean(self, value):
"""
Validates the given value against all of self.fields, which is a
list of Field instances.
"""
Field.clean(self, value)
for field in self.fields:
value = field.clean(value)
return value

197
django/newforms/forms.py Normal file
View File

@ -0,0 +1,197 @@
"""
Form classes
"""
from django.utils.datastructures import SortedDict
from fields import Field
from widgets import TextInput, Textarea
from util import ErrorDict, ErrorList, ValidationError
NON_FIELD_ERRORS = '__all__'
def pretty_name(name):
"Converts 'first_name' to 'First name'"
name = name[0].upper() + name[1:]
return name.replace('_', ' ')
class SortedDictFromList(SortedDict):
"A dictionary that keeps its keys in the order in which they're inserted."
# This is different than django.utils.datastructures.SortedDict, because
# this takes a list/tuple as the argument to __init__().
def __init__(self, data=None):
if data is None: data = []
self.keyOrder = [d[0] for d in data]
dict.__init__(self, dict(data))
class DeclarativeFieldsMetaclass(type):
"Metaclass that converts Field attributes to a dictionary called 'fields'."
def __new__(cls, name, bases, attrs):
fields = [(name, attrs.pop(name)) for name, obj in attrs.items() if isinstance(obj, Field)]
fields.sort(lambda x, y: cmp(x[1].creation_counter, y[1].creation_counter))
attrs['fields'] = SortedDictFromList(fields)
return type.__new__(cls, name, bases, attrs)
class Form(object):
"A collection of Fields, plus their associated data."
__metaclass__ = DeclarativeFieldsMetaclass
def __init__(self, data=None, auto_id=False): # TODO: prefix stuff
self.data = data or {}
self.auto_id = auto_id
self.clean_data = None # Stores the data after clean() has been called.
self.__errors = None # Stores the errors after clean() has been called.
def __str__(self):
return self.as_table()
def __iter__(self):
for name, field in self.fields.items():
yield BoundField(self, field, name)
def __getitem__(self, name):
"Returns a BoundField with the given name."
try:
field = self.fields[name]
except KeyError:
raise KeyError('Key %r not found in Form' % name)
return BoundField(self, field, name)
def clean(self):
if self.__errors is None:
self.full_clean()
return self.clean_data
def errors(self):
"Returns an ErrorDict for self.data"
if self.__errors is None:
self.full_clean()
return self.__errors
def is_valid(self):
"""
Returns True if the form has no errors. Otherwise, False. This exists
solely for convenience, so client code can use positive logic rather
than confusing negative logic ("if not form.errors()").
"""
return not bool(self.errors())
def as_table(self):
"Returns this form rendered as HTML <tr>s -- excluding the <table></table>."
return u'\n'.join(['<tr><td>%s:</td><td>%s</td></tr>' % (pretty_name(name), BoundField(self, field, name)) for name, field in self.fields.items()])
def as_ul(self):
"Returns this form rendered as HTML <li>s -- excluding the <ul></ul>."
return u'\n'.join(['<li>%s: %s</li>' % (pretty_name(name), BoundField(self, field, name)) for name, field in self.fields.items()])
def as_table_with_errors(self):
"Returns this form rendered as HTML <tr>s, with errors."
output = []
if self.errors().get(NON_FIELD_ERRORS):
# Errors not corresponding to a particular field are displayed at the top.
output.append('<tr><td colspan="2"><ul>%s</ul></td></tr>' % '\n'.join(['<li>%s</li>' % e for e in self.errors()[NON_FIELD_ERRORS]]))
for name, field in self.fields.items():
bf = BoundField(self, field, name)
if bf.errors:
output.append('<tr><td colspan="2"><ul>%s</ul></td></tr>' % '\n'.join(['<li>%s</li>' % e for e in bf.errors]))
output.append('<tr><td>%s:</td><td>%s</td></tr>' % (pretty_name(name), bf))
return u'\n'.join(output)
def as_ul_with_errors(self):
"Returns this form rendered as HTML <li>s, with errors."
output = []
if self.errors().get(NON_FIELD_ERRORS):
# Errors not corresponding to a particular field are displayed at the top.
output.append('<li><ul>%s</ul></li>' % '\n'.join(['<li>%s</li>' % e for e in self.errors()[NON_FIELD_ERRORS]]))
for name, field in self.fields.items():
bf = BoundField(self, field, name)
line = '<li>'
if bf.errors:
line += '<ul>%s</ul>' % '\n'.join(['<li>%s</li>' % e for e in bf.errors])
line += '%s: %s</li>' % (pretty_name(name), bf)
output.append(line)
return u'\n'.join(output)
def full_clean(self):
"""
Cleans all of self.data and populates self.__errors and self.clean_data.
"""
self.clean_data = {}
errors = ErrorDict()
for name, field in self.fields.items():
value = self.data.get(name, None)
try:
value = field.clean(value)
self.clean_data[name] = value
if hasattr(self, 'clean_%s' % name):
value = getattr(self, 'clean_%s' % name)()
self.clean_data[name] = value
except ValidationError, e:
errors[name] = e.messages
try:
self.clean_data = self.clean()
except ValidationError, e:
errors[NON_FIELD_ERRORS] = e.messages
if errors:
self.clean_data = None
self.__errors = errors
def clean(self):
"""
Hook for doing any extra form-wide cleaning after Field.clean() been
called on every field.
"""
return self.clean_data
class BoundField(object):
"A Field plus data"
def __init__(self, form, field, name):
self._form = form
self._field = field
self._name = name
def __str__(self):
"Renders this field as an HTML widget."
# Use the 'widget' attribute on the field to determine which type
# of HTML widget to use.
return self.as_widget(self._field.widget)
def _errors(self):
"""
Returns an ErrorList for this field. Returns an empty ErrorList
if there are none.
"""
try:
return self._form.errors()[self._name]
except KeyError:
return ErrorList()
errors = property(_errors)
def as_widget(self, widget, attrs=None):
attrs = attrs or {}
auto_id = self.auto_id
if not attrs.has_key('id') and not widget.attrs.has_key('id') and auto_id:
attrs['id'] = auto_id
return widget.render(self._name, self._form.data.get(self._name, None), attrs=attrs)
def as_text(self, attrs=None):
"""
Returns a string of HTML for representing this as an <input type="text">.
"""
return self.as_widget(TextInput(), attrs)
def as_textarea(self, attrs=None):
"Returns a string of HTML for representing this as a <textarea>."
return self.as_widget(Textarea(), attrs)
def _auto_id(self):
"""
Calculates and returns the ID attribute for this BoundField, if the
associated Form has specified auto_id. Returns an empty string otherwise.
"""
auto_id = self._form.auto_id
if auto_id and '%s' in str(auto_id):
return str(auto_id) % self._name
elif auto_id:
return self._name
return ''
auto_id = property(_auto_id)

57
django/newforms/util.py Normal file
View File

@ -0,0 +1,57 @@
# Default encoding for input byte strings.
DEFAULT_ENCODING = 'utf-8' # TODO: First look at django.conf.settings, then fall back to this.
def smart_unicode(s):
if not isinstance(s, basestring):
s = unicode(str(s))
elif not isinstance(s, unicode):
s = unicode(s, DEFAULT_ENCODING)
return s
class ErrorDict(dict):
"""
A collection of errors that knows how to display itself in various formats.
The dictionary keys are the field names, and the values are the errors.
"""
def __str__(self):
return self.as_ul()
def as_ul(self):
if not self: return u''
return u'<ul class="errorlist">%s</ul>' % ''.join([u'<li>%s%s</li>' % (k, v) for k, v in self.items()])
def as_text(self):
return u'\n'.join([u'* %s\n%s' % (k, u'\n'.join([u' * %s' % i for i in v])) for k, v in self.items()])
class ErrorList(list):
"""
A collection of errors that knows how to display itself in various formats.
"""
def __str__(self):
return self.as_ul()
def as_ul(self):
if not self: return u''
return u'<ul class="errorlist">%s</ul>' % ''.join([u'<li>%s</li>' % e for e in self])
def as_text(self):
if not self: return u''
return u'\n'.join([u'* %s' % e for e in self])
class ValidationError(Exception):
def __init__(self, message):
"ValidationError can be passed a string or a list."
if isinstance(message, list):
self.messages = ErrorList([smart_unicode(msg) for msg in message])
else:
assert isinstance(message, basestring), ("%s should be a basestring" % repr(message))
message = smart_unicode(message)
self.messages = ErrorList([message])
def __str__(self):
# This is needed because, without a __str__(), printing an exception
# instance would result in this:
# AttributeError: ValidationError instance has no attribute 'args'
# See http://www.python.org/doc/current/tut/node10.html#handling
return repr(self.messages)

153
django/newforms/widgets.py Normal file
View File

@ -0,0 +1,153 @@
"""
HTML Widget classes
"""
__all__ = (
'Widget', 'TextInput', 'PasswordInput', 'HiddenInput', 'FileInput',
'Textarea', 'CheckboxInput',
'Select', 'SelectMultiple', 'RadioSelect',
)
from util import smart_unicode
from django.utils.html import escape
from itertools import chain
try:
set # Only available in Python 2.4+
except NameError:
from sets import Set as set # Python 2.3 fallback
# Converts a dictionary to a single string with key="value", XML-style with
# a leading space. Assumes keys do not need to be XML-escaped.
flatatt = lambda attrs: u''.join([u' %s="%s"' % (k, escape(v)) for k, v in attrs.items()])
class Widget(object):
requires_data_list = False # Determines whether render()'s 'value' argument should be a list.
def __init__(self, attrs=None):
self.attrs = attrs or {}
def render(self, name, value):
raise NotImplementedError
def build_attrs(self, extra_attrs=None, **kwargs):
attrs = dict(self.attrs, **kwargs)
if extra_attrs:
attrs.update(extra_attrs)
return attrs
class Input(Widget):
"""
Base class for all <input> widgets (except type='checkbox' and
type='radio', which are special).
"""
input_type = None # Subclasses must define this.
def render(self, name, value, attrs=None):
if value is None: value = ''
final_attrs = self.build_attrs(attrs, type=self.input_type, name=name)
if value != '': final_attrs['value'] = smart_unicode(value) # Only add the 'value' attribute if a value is non-empty.
return u'<input%s />' % flatatt(final_attrs)
class TextInput(Input):
input_type = 'text'
class PasswordInput(Input):
input_type = 'password'
class HiddenInput(Input):
input_type = 'hidden'
class FileInput(Input):
input_type = 'file'
class Textarea(Widget):
def render(self, name, value, attrs=None):
if value is None: value = ''
value = smart_unicode(value)
final_attrs = self.build_attrs(attrs, name=name)
return u'<textarea%s>%s</textarea>' % (flatatt(final_attrs), escape(value))
class CheckboxInput(Widget):
def render(self, name, value, attrs=None):
final_attrs = self.build_attrs(attrs, type='checkbox', name=name)
if value: final_attrs['checked'] = 'checked'
return u'<input%s />' % flatatt(final_attrs)
class Select(Widget):
def __init__(self, attrs=None, choices=()):
# choices can be any iterable
self.attrs = attrs or {}
self.choices = choices
def render(self, name, value, attrs=None, choices=()):
if value is None: value = ''
final_attrs = self.build_attrs(attrs, name=name)
output = [u'<select%s>' % flatatt(final_attrs)]
str_value = smart_unicode(value) # Normalize to string.
for option_value, option_label in chain(self.choices, choices):
option_value = smart_unicode(option_value)
selected_html = (option_value == str_value) and u' selected="selected"' or ''
output.append(u'<option value="%s"%s>%s</option>' % (escape(option_value), selected_html, escape(smart_unicode(option_label))))
output.append(u'</select>')
return u'\n'.join(output)
class SelectMultiple(Widget):
requires_data_list = True
def __init__(self, attrs=None, choices=()):
# choices can be any iterable
self.attrs = attrs or {}
self.choices = choices
def render(self, name, value, attrs=None, choices=()):
if value is None: value = []
final_attrs = self.build_attrs(attrs, name=name)
output = [u'<select multiple="multiple"%s>' % flatatt(final_attrs)]
str_values = set([smart_unicode(v) for v in value]) # Normalize to strings.
for option_value, option_label in chain(self.choices, choices):
option_value = smart_unicode(option_value)
selected_html = (option_value in str_values) and ' selected="selected"' or ''
output.append(u'<option value="%s"%s>%s</option>' % (escape(option_value), selected_html, escape(smart_unicode(option_label))))
output.append(u'</select>')
return u'\n'.join(output)
class RadioInput(object):
"An object used by RadioFieldRenderer that represents a single <input type='radio'>."
def __init__(self, name, value, attrs, choice):
self.name, self.value = name, value
self.attrs = attrs or {}
self.choice_value, self.choice_label = choice
def __str__(self):
return u'<label>%s %s</label>' % (self.tag(), self.choice_label)
def is_checked(self):
return self.value == smart_unicode(self.choice_value)
def tag(self):
final_attrs = dict(self.attrs, type='radio', name=self.name, value=self.choice_value)
if self.is_checked():
final_attrs['checked'] = 'checked'
return u'<input%s />' % flatatt(final_attrs)
class RadioFieldRenderer(object):
"An object used by RadioSelect to enable customization of radio widgets."
def __init__(self, name, value, attrs, choices):
self.name, self.value, self.attrs = name, value, attrs
self.choices = choices
def __iter__(self):
for choice in self.choices:
yield RadioInput(self.name, self.value, self.attrs, choice)
def __str__(self):
"Outputs a <ul> for this set of radio fields."
return u'<ul>\n%s\n</ul>' % u'\n'.join([u'<li>%s</li>' % w for w in self])
class RadioSelect(Select):
def render(self, name, value, attrs=None, choices=()):
"Returns a RadioFieldRenderer instance rather than a Unicode string."
if value is None: value = ''
str_value = smart_unicode(value) # Normalize to string.
return RadioFieldRenderer(name, str_value, attrs, list(chain(self.choices, choices)))
class CheckboxSelectMultiple(Widget):
pass

View File

@ -868,8 +868,11 @@ class Library(object):
dict = func(*args)
if not getattr(self, 'nodelist', False):
from django.template.loader import get_template
t = get_template(file_name)
from django.template.loader import get_template, select_template
if hasattr(file_name, '__iter__'):
t = select_template(file_name)
else:
t = get_template(file_name)
self.nodelist = t.nodelist
return self.nodelist.render(context_class(dict))
@ -883,7 +886,7 @@ def get_library(module_name):
lib = libraries.get(module_name, None)
if not lib:
try:
mod = __import__(module_name, '', '', [''])
mod = __import__(module_name, {}, {}, [''])
except ImportError, e:
raise InvalidTemplateLibrary, "Could not load template library from %s, %s" % (module_name, e)
try:

View File

@ -69,7 +69,7 @@ def get_standard_processors():
i = path.rfind('.')
module, attr = path[:i], path[i+1:]
try:
mod = __import__(module, '', '', [attr])
mod = __import__(module, {}, {}, [attr])
except ImportError, e:
raise ImproperlyConfigured, 'Error importing request processor module %s: "%s"' % (module, e)
try:

View File

@ -421,7 +421,11 @@ def filesizeformat(bytes):
Format the value like a 'human-readable' file size (i.e. 13 KB, 4.1 MB, 102
bytes, etc).
"""
bytes = float(bytes)
try:
bytes = float(bytes)
except TypeError:
return "0 bytes"
if bytes < 1024:
return "%d byte%s" % (bytes, bytes != 1 and 's' or '')
if bytes < 1024 * 1024:

View File

@ -124,17 +124,27 @@ class ForNode(Node):
return nodelist.render(context)
class IfChangedNode(Node):
def __init__(self, nodelist):
def __init__(self, nodelist, *varlist):
self.nodelist = nodelist
self._last_seen = None
self._varlist = varlist
def render(self, context):
if context.has_key('forloop') and context['forloop']['first']:
self._last_seen = None
content = self.nodelist.render(context)
if content != self._last_seen:
try:
if self._varlist:
# Consider multiple parameters.
# This automatically behaves like a OR evaluation of the multiple variables.
compare_to = [resolve_variable(var, context) for var in self._varlist]
else:
compare_to = self.nodelist.render(context)
except VariableDoesNotExist:
compare_to = None
if compare_to != self._last_seen:
firstloop = (self._last_seen == None)
self._last_seen = content
self._last_seen = compare_to
context.push()
context['ifchanged'] = {'firstloop': firstloop}
content = self.nodelist.render(context)
@ -634,23 +644,34 @@ def ifchanged(parser, token):
"""
Check if a value has changed from the last iteration of a loop.
The 'ifchanged' block tag is used within a loop. It checks its own rendered
contents against its previous state and only displays its content if the
value has changed::
The 'ifchanged' block tag is used within a loop. It has two possible uses.
<h1>Archive for {{ year }}</h1>
1. Checks its own rendered contents against its previous state and only
displays the content if it has changed. For example, this displays a list of
days, only displaying the month if it changes::
{% for date in days %}
{% ifchanged %}<h3>{{ date|date:"F" }}</h3>{% endifchanged %}
<a href="{{ date|date:"M/d"|lower }}/">{{ date|date:"j" }}</a>
{% endfor %}
<h1>Archive for {{ year }}</h1>
{% for date in days %}
{% ifchanged %}<h3>{{ date|date:"F" }}</h3>{% endifchanged %}
<a href="{{ date|date:"M/d"|lower }}/">{{ date|date:"j" }}</a>
{% endfor %}
2. If given a variable, check whether that variable has changed. For example, the
following shows the date every time it changes, but only shows the hour if both
the hour and the date have changed::
{% for date in days %}
{% ifchanged date.date %} {{ date.date }} {% endifchanged %}
{% ifchanged date.hour date.date %}
{{ date.hour }}
{% endifchanged %}
{% endfor %}
"""
bits = token.contents.split()
if len(bits) != 1:
raise TemplateSyntaxError, "'ifchanged' tag takes no arguments"
nodelist = parser.parse(('endifchanged',))
parser.delete_first_token()
return IfChangedNode(nodelist)
return IfChangedNode(nodelist, *bits[1:])
ifchanged = register.tag(ifchanged)
#@register.tag

View File

@ -15,9 +15,9 @@ for app in settings.INSTALLED_APPS:
m, a = app[:i], app[i+1:]
try:
if a is None:
mod = __import__(m, '', '', [])
mod = __import__(m, {}, {}, [])
else:
mod = getattr(__import__(m, '', '', [a]), a)
mod = getattr(__import__(m, {}, {}, [a]), a)
except ImportError, e:
raise ImproperlyConfigured, 'ImportError %s: %s' % (app, e.args[0])
template_dir = os.path.join(os.path.dirname(mod.__file__), 'templates')

View File

@ -2,6 +2,6 @@ from django.conf import settings
for a in settings.INSTALLED_APPS:
try:
__path__.extend(__import__(a + '.templatetags', '', '', ['']).__path__)
__path__.extend(__import__(a + '.templatetags', {}, {}, ['']).__path__)
except ImportError:
pass

View File

@ -28,7 +28,7 @@ def build_suite(app_module):
# models module
try:
app_path = app_module.__name__.split('.')[:-1]
test_module = __import__('.'.join(app_path + [TEST_MODULE]), [], [], TEST_MODULE)
test_module = __import__('.'.join(app_path + [TEST_MODULE]), {}, {}, TEST_MODULE)
suite.addTest(unittest.defaultTestLoader.loadTestsFromModule(test_module))
try:

View File

@ -75,7 +75,7 @@ def technical_500_response(request, exc_type, exc_value, tb):
loader_debug_info = []
for loader in template_source_loaders:
try:
source_list_func = getattr(__import__(loader.__module__, '', '', ['get_template_sources']), 'get_template_sources')
source_list_func = getattr(__import__(loader.__module__, {}, {}, ['get_template_sources']), 'get_template_sources')
# NOTE: This assumes exc_value is the name of the template that
# the loader attempted to load.
template_list = [{'name': t, 'exists': os.path.exists(t)} \

View File

@ -2,12 +2,18 @@ from django.shortcuts import render_to_response
from django.template import RequestContext
from django.http import HttpResponse, HttpResponsePermanentRedirect, HttpResponseGone
def direct_to_template(request, template, **kwargs):
def direct_to_template(request, template, extra_context={}, **kwargs):
"""
Render a given template with any extra URL parameters in the context as
``{{ params }}``.
"""
return render_to_response(template, {'params' : kwargs}, context_instance=RequestContext(request))
dictionary = {'params': kwargs}
for key, value in extra_context.items():
if callable(value):
dictionary[key] = value()
else:
dictionary[key] = value
return render_to_response(template, dictionary, context_instance=RequestContext(request))
def redirect_to(request, url, **kwargs):
"""
@ -18,7 +24,7 @@ def redirect_to(request, url, **kwargs):
``/foo/<id>/`` to ``/bar/<id>/``, you could use the following URLconf::
urlpatterns = patterns('',
('^foo/(?p<id>\d+)/$', 'django.views.generic.simple.redirect_to', {'url' : '/bar/%(id)s/'}),
('^foo/(?P<id>\d+)/$', 'django.views.generic.simple.redirect_to', {'url' : '/bar/%(id)s/'}),
)
If the given url is ``None``, a HttpResponseGone (410) will be issued.

View File

@ -745,7 +745,7 @@ messages are made available in the `template context`_ as the template variable
{% if messages %}
<ul>
{% for message in messages %}
<li>{{ message.message }}</li>
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}

View File

@ -610,6 +610,15 @@ fails. If no message is passed in, a default message is used.
string "123" is less than the string "2", for example. If you don't want
string comparison here, you will need to write your own validator.
``NumberIsInRange``
Takes two boundary numbers, ``lower`` and ``upper``, and checks that the
field is greater than ``lower`` (if given) and less than ``upper`` (if
given).
Both checks are inclusive. That is, ``NumberIsInRange(10, 20)`` will allow
values of both 10 and 20. This validator only checks numeric values
(e.g., float and integer values).
``IsAPowerOf``
Takes an integer argument and when called as a validator, checks that the
field being validated is a power of the integer.

View File

@ -92,6 +92,14 @@ which is a dictionary of the parameters captured in the URL.
* ``template``: The full name of a template to use.
**Optional arguments:**
* ``extra_context``: A dictionary of values to add to the template
context. By default, this is an empty dictionary. If a value in the
dictionary is callable, the generic view will call it
just before rendering the template. (**This is new in the
Django development version.**)
**Example:**
Given the following URL patterns::
@ -171,7 +179,7 @@ a date in the *future* are not included unless you set ``allow_future`` to
template. By default, it's ``django.template.loader``.
* ``extra_context``: A dictionary of values to add to the template
context. By default, this is an empty dictionary.
context. By default, this is an empty dictionary. If a value in the
dictionary is callable, the generic view will call it
just before rendering the template.

View File

@ -43,6 +43,11 @@ This tells Apache: "Use mod_python for any URL at or under '/mysite/', using the
Django mod_python handler." It passes the value of ``DJANGO_SETTINGS_MODULE``
so mod_python knows which settings to use.
Note that we're using the ``<Location>`` directive, not the ``<Directory>``
directive. The latter is used for pointing at places on your filesystem,
whereas ``<Location>`` points at places in the URL structure of a Web site.
``<Directory>`` would be meaningless here.
Also, if you've manually altered your ``PYTHONPATH`` to put your Django project
on it, you'll need to tell mod_python::

View File

@ -265,6 +265,14 @@ Default: ``''`` (Empty string)
The name of the database to use. For SQLite, it's the full path to the database
file.
DATABASE_OPTIONS
----------------
Default: ``{}`` (Empty dictionary)
Extra parameters to use when connecting to the database. Consult backend
module's document for available keywords.
DATABASE_PASSWORD
-----------------
@ -814,6 +822,16 @@ manual configuration option (see below), Django will *not* touch the ``TZ``
environment variable, and it'll be up to you to ensure your processes are
running in the correct environment.
URL_VALIDATOR_USER_AGENT
------------------------
Default: ``Django/<version> (http://www.djangoproject.com/)``
The string to use as the ``User-Agent`` header when checking to see if URLs
exist (see the ``verify_exists`` option on URLField_).
.. URLField: ../model_api/#urlfield
USE_ETAGS
---------

View File

@ -5,9 +5,9 @@ The sitemap framework
**New in Django development version**.
Django comes with a high-level sitemap-generating framework that makes
creating `Google Sitemap`_ XML files easy.
creating sitemap_ XML files easy.
.. _Google Sitemap: http://www.google.com/webmasters/sitemaps/docs/en/protocol.html
.. _sitemap: http://www.sitemaps.org/
Overview
========
@ -55,11 +55,12 @@ URLconf_:
This tells Django to build a sitemap when a client accesses ``/sitemap.xml``.
The name of the sitemap file is not important, but the location is. Google will
only index links in your sitemap for the current URL level and below. For
instance, if ``sitemap.xml`` lives in your root directory, it may reference any
URL in your site. However, if your sitemap lives at ``/content/sitemap.xml``,
it may only reference URLs that begin with ``/content/``.
The name of the sitemap file is not important, but the location is. Search
engines will only index links in your sitemap for the current URL level and
below. For instance, if ``sitemap.xml`` lives in your root directory, it may
reference any URL in your site. However, if your sitemap lives at
``/content/sitemap.xml``, it may only reference URLs that begin with
``/content/``.
The sitemap view takes an extra, required argument: ``{'sitemaps': sitemaps}``.
``sitemaps`` should be a dictionary that maps a short section label (e.g.,
@ -199,9 +200,9 @@ If it's an attribute, its value should be either a string or float representing
the priority of *every* object returned by ``items()``.
Example values for ``priority``: ``0.4``, ``1.0``. The default priority of a
page is ``0.5``. See Google's documentation for more documentation.
page is ``0.5``. See the `sitemaps.org documentation`_ for more.
.. _Google's documentation: http://www.google.com/webmasters/sitemaps/docs/en/protocol.html
.. _sitemaps.org documentation: http://www.sitemaps.org/protocol.html#prioritydef
Shortcuts
=========

View File

@ -31,7 +31,7 @@ How to do it
Just put this in your URLconf_::
(r'^site_media/(.*)$', 'django.views.static.serve', {'document_root': '/path/to/media'}),
(r'^site_media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': '/path/to/media'}),
...where ``site_media`` is the URL where your media will be rooted, and
``/path/to/media`` is the filesystem root for your media.
@ -60,7 +60,7 @@ listings for directories.
Example::
(r'^site_media/(.*)$', 'django.views.static.serve', {'document_root': '/path/to/media', 'show_indexes': True}),
(r'^site_media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': '/path/to/media', 'show_indexes': True}),
You can customize the index view by creating a template called
``static/directory_index``. That template gets two objects in its context:

View File

@ -95,7 +95,7 @@ latest five news items::
from django.contrib.syndication.feeds import Feed
from chicagocrime.models import NewsItem
class SiteNewsFeed(Feed):
class LatestEntries(Feed):
title = "Chicagocrime.org site news"
link = "/sitenews/"
description = "Updates on changes and additions to chicagocrime.org."
@ -120,14 +120,14 @@ One thing's left to do. In an RSS feed, each ``<item>`` has a ``<title>``,
put into those elements.
* To specify the contents of ``<title>`` and ``<description>``, create
`Django templates`_ called ``feeds/sitenews_title.html`` and
``feeds/sitenews_description.html``, where ``sitenews`` is the ``slug``
`Django templates`_ called ``feeds/latest_title.html`` and
``feeds/latest_description.html``, where ``latest`` is the ``slug``
specified in the URLconf for the given feed. Note the ``.html`` extension
is required. The RSS system renders that template for each item, passing
it two template context variables:
* ``{{ obj }}`` -- The current object (one of whichever objects you
returned in ``items()``).
returned in ``items()``).
* ``{{ site }}`` -- A ``django.models.core.sites.Site`` object
representing the current site. This is useful for
``{{ site.domain }}`` or ``{{ site.name }}``.
@ -145,6 +145,16 @@ put into those elements.
Both ``get_absolute_url()`` and ``item_link()`` should return the item's
URL as a normal Python string.
* For the LatestEntries example above, we could have very simple feed templates:
* latest_title.html::
{{ obj.title }}
* latest_description.html::
{{ obj.description }}
.. _chicagocrime.org: http://www.chicagocrime.org/
.. _object-relational mapper: http://www.djangoproject.com/documentation/db_api/
.. _Django templates: http://www.djangoproject.com/documentation/templates/

View File

@ -473,7 +473,7 @@ block are output::
In the above, if ``athlete_list`` is not empty, the number of athletes will be
displayed by the ``{{ athlete_list|length }}`` variable.
As you can see, the ``if`` tag can take an option ``{% else %}`` clause that
As you can see, the ``if`` tag can take an optional ``{% else %}`` clause that
will be displayed if the test fails.
``if`` tags may use ``and``, ``or`` or ``not`` to test a number of variables or
@ -525,16 +525,29 @@ ifchanged
Check if a value has changed from the last iteration of a loop.
The ``ifchanged`` block tag is used within a loop. It checks its own rendered
contents against its previous state and only displays its content if the value
has changed::
The 'ifchanged' block tag is used within a loop. It has two possible uses.
<h1>Archive for {{ year }}</h1>
1. Checks its own rendered contents against its previous state and only
displays the content if it has changed. For example, this displays a list of
days, only displaying the month if it changes::
{% for day in days %}
{% ifchanged %}<h3>{{ day|date:"F" }}</h3>{% endifchanged %}
<a href="{{ day|date:"M/d"|lower }}/">{{ day|date:"j" }}</a>
{% endfor %}
<h1>Archive for {{ year }}</h1>
{% for date in days %}
{% ifchanged %}<h3>{{ date|date:"F" }}</h3>{% endifchanged %}
<a href="{{ date|date:"M/d"|lower }}/">{{ date|date:"j" }}</a>
{% endfor %}
2. **New in Django development version.** If given a variable, check whether that
variable has changed. For example, the following shows the date every time it
changes, but only shows the hour if both the hour and the date has changed::
{% for date in days %}
{% ifchanged date.date %} {{ date.date }} {% endifchanged %}
{% ifchanged date.hour date.date %}
{{ date.hour }}
{% endifchanged %}
{% endfor %}
ifequal
~~~~~~~
@ -558,7 +571,7 @@ The arguments can be hard-coded strings, so the following is valid::
It is only possible to compare an argument to template variables or strings.
You cannot check for equality with Python objects such as ``True`` or
``False``. If you need to test if something is true or false, use the ``if``
and ``ifnot`` tags instead.
tag instead.
ifnotequal
~~~~~~~~~~

View File

@ -321,7 +321,7 @@ Note::
def some_view(request):
# ...
return render_to_response('my_template'html',
return render_to_response('my_template.html',
my_data_dictionary,
context_instance=RequestContext(request))

View File

@ -10,7 +10,7 @@ used to validate that code behaves as expected. When refactoring or
modifying code, tests serve as a guide to ensure that behavior hasn't
changed unexpectedly as a result of the refactor.
Testing an web application is a complex task, as there are many
Testing a web application is a complex task, as there are many
components of a web application that must be validated and tested. To
help you test your application, Django provides a test execution
framework, and range of utilities that can be used to stimulate and

View File

@ -192,13 +192,13 @@ objects" and "display a detail page for a particular type of object."
``object_id`` for the generic views.
By default, the ``object_detail`` generic view uses a template called
``<app name>/<module name>_detail.html``. In our case, it'll use the template
``<app name>/<model name>_detail.html``. In our case, it'll use the template
``"polls/poll_detail.html"``. Thus, rename your ``polls/detail.html`` template to
``polls/poll_detail.html``, and change the ``render_to_response()`` line in
``vote()``.
Similarly, the ``object_list`` generic view uses a template called
``<app name>/<module name>_list.html``. Thus, rename ``polls/index.html`` to
``<app name>/<model name>_list.html``. Thus, rename ``polls/index.html`` to
``polls/poll_list.html``.
Because we have more than one entry in the URLconf that uses ``object_detail``

View File

@ -64,4 +64,17 @@ True
>>> paginator.last_on_page(1)
9
# Add a few more records to test out the orphans feature.
>>> for x in range(10, 13):
... Article(headline="Article %s" % x, pub_date=datetime(2006, 10, 6)).save()
# With orphans set to 3 and 10 items per page, we should get all 12 items on a single page:
>>> paginator = ObjectPaginator(Article.objects.all(), 10, orphans=3)
>>> paginator.pages
1
# With orphans only set to 1, we should get two pages:
>>> paginator = ObjectPaginator(Article.objects.all(), 10, orphans=1)
>>> paginator.pages
2
"""}

View File

View File

File diff suppressed because it is too large Load Diff

View File

@ -328,6 +328,21 @@ class Templates(unittest.TestCase):
'ifchanged05': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}', { 'num': (1, 1, 1), 'numx': (1, 2, 3)}, '1123123123'),
'ifchanged06': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}', { 'num': (1, 1, 1), 'numx': (2, 2, 2)}, '1222'),
'ifchanged07': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% for y in numy %}{% ifchanged %}{{ y }}{% endifchanged %}{% endfor %}{% endfor %}{% endfor %}', { 'num': (1, 1, 1), 'numx': (2, 2, 2), 'numy': (3, 3, 3)}, '1233323332333'),
# Test one parameter given to ifchanged.
'ifchanged-param01': ('{% for n in num %}{% ifchanged n %}..{% endifchanged %}{{ n }}{% endfor %}', { 'num': (1,2,3) }, '..1..2..3'),
'ifchanged-param02': ('{% for n in num %}{% for x in numx %}{% ifchanged n %}..{% endifchanged %}{{ x }}{% endfor %}{% endfor %}', { 'num': (1,2,3), 'numx': (5,6,7) }, '..567..567..567'),
# Test multiple parameters to ifchanged.
'ifchanged-param03': ('{% for n in num %}{{ n }}{% for x in numx %}{% ifchanged x n %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}', { 'num': (1,1,2), 'numx': (5,6,6) }, '156156256'),
# Test a date+hour like construct, where the hour of the last day
# is the same but the date had changed, so print the hour anyway.
'ifchanged-param04': ('{% for d in days %}{% ifchanged %}{{ d.day }}{% endifchanged %}{% for h in d.hours %}{% ifchanged d h %}{{ h }}{% endifchanged %}{% endfor %}{% endfor %}', {'days':[{'day':1, 'hours':[1,2,3]},{'day':2, 'hours':[3]},] }, '112323'),
# Logically the same as above, just written with explicit
# ifchanged for the day.
'ifchanged-param04': ('{% for d in days %}{% ifchanged d.day %}{{ d.day }}{% endifchanged %}{% for h in d.hours %}{% ifchanged d.day h %}{{ h }}{% endifchanged %}{% endfor %}{% endfor %}', {'days':[{'day':1, 'hours':[1,2,3]},{'day':2, 'hours':[3]},] }, '112323'),
### IFEQUAL TAG ###########################################################
'ifequal01': ("{% ifequal a b %}yes{% endifequal %}", {"a": 1, "b": 2}, ""),