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

newforms-admin: Merged from trunk up to [6952].

git-svn-id: http://code.djangoproject.com/svn/django/branches/newforms-admin@6955 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Joseph Kocherhans 2007-12-19 05:20:55 +00:00
parent 3f494f1823
commit f4c7a0dcb6
96 changed files with 1606 additions and 973 deletions

View File

@ -131,6 +131,7 @@ answer newbie questions, and generally made Django that much better:
Matthew Flanagan <http://wadofstuff.blogspot.com>
Eric Floehr <eric@intellovations.com>
Vincent Foley <vfoleybourgon@yahoo.ca>
Rudolph Froger <rfroger@estrate.nl>
Jorge Gajon <gajon@gajon.org>
gandalf@owca.info
Marc Garcia <marc.garcia@accopensys.com>
@ -306,6 +307,7 @@ answer newbie questions, and generally made Django that much better:
Georgi Stanojevski <glisha@gmail.com>
Vasiliy Stavenko <stavenko@gmail.com>
Thomas Steinacher <http://www.eggdrop.ch/>
Johan C. Stöver <johan@nilling.nl>
nowell strite
Thomas Stromberg <tstromberg@google.com>
Sundance
@ -333,6 +335,7 @@ answer newbie questions, and generally made Django that much better:
tt@gurgle.no
Amit Upadhyay
Geert Vanderkelen
I.S. van Oostveen <v.oostveen@idca.nl>
viestards.lists@gmail.com
George Vilches <gav@thataddress.com>
Vlado <vlado@labath.org>

View File

@ -52,7 +52,9 @@ class LazySettings(object):
if not settings_module: # If it's set but is an empty string.
raise KeyError
except KeyError:
raise ImportError, "Environment variable %s is undefined so settings cannot be imported." % ENVIRONMENT_VARIABLE # NOTE: This is arguably an EnvironmentError, but that causes problems with Python's interactive help
# NOTE: This is arguably an EnvironmentError, but that causes
# problems with Python's interactive help.
raise ImportError("Settings cannot be imported, because environment variable %s is undefined." % ENVIRONMENT_VARIABLE)
self._target = Settings(settings_module)

View File

@ -5,9 +5,9 @@ msgid ""
msgstr ""
"Project-Id-Version: django\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2007-11-05 17:33+0100\n"
"PO-Revision-Date: 2007-11-05 17:34+0100\n"
"Last-Translator: Marc Garcia <marc.garcia@accopensys.com>\n"
"POT-Creation-Date: 2007-12-02 22:26+0100\n"
"PO-Revision-Date: 2007-12-02 22:32+0100\n"
"Last-Translator: Marc Fargas <telenieko@telenieko.com>\n"
"Language-Team: <es@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -194,7 +194,7 @@ msgstr "Xinés simplificat"
msgid "Traditional Chinese"
msgstr "Xinés tradicional"
#: contrib/admin/filterspecs.py:42
#: contrib/admin/filterspecs.py:44
#, python-format
msgid ""
"<h3>By %s:</h3>\n"
@ -203,71 +203,71 @@ msgstr ""
"<h3>Per %s:</h3>\n"
"<ul>\n"
#: contrib/admin/filterspecs.py:72 contrib/admin/filterspecs.py:90
#: contrib/admin/filterspecs.py:145 contrib/admin/filterspecs.py:171
#: contrib/admin/filterspecs.py:74 contrib/admin/filterspecs.py:92
#: contrib/admin/filterspecs.py:147 contrib/admin/filterspecs.py:173
msgid "All"
msgstr "Tots"
#: contrib/admin/filterspecs.py:111
#: contrib/admin/filterspecs.py:113
msgid "Any date"
msgstr "Qualsevol data"
#: contrib/admin/filterspecs.py:112
#: contrib/admin/filterspecs.py:114
msgid "Today"
msgstr "Avui"
#: contrib/admin/filterspecs.py:115
#: contrib/admin/filterspecs.py:117
msgid "Past 7 days"
msgstr "Últims 7 dies"
#: contrib/admin/filterspecs.py:117
#: contrib/admin/filterspecs.py:119
msgid "This month"
msgstr "Aquest mes"
#: contrib/admin/filterspecs.py:119
#: contrib/admin/filterspecs.py:121
msgid "This year"
msgstr "Aquest any"
#: contrib/admin/filterspecs.py:145 newforms/widgets.py:221
#: oldforms/__init__.py:591
#: contrib/admin/filterspecs.py:147 newforms/widgets.py:231
#: oldforms/__init__.py:592
msgid "Yes"
msgstr "Si"
#: contrib/admin/filterspecs.py:145 newforms/widgets.py:221
#: oldforms/__init__.py:591
#: contrib/admin/filterspecs.py:147 newforms/widgets.py:231
#: oldforms/__init__.py:592
msgid "No"
msgstr "No"
#: contrib/admin/filterspecs.py:152 newforms/widgets.py:221
#: oldforms/__init__.py:591
#: contrib/admin/filterspecs.py:154 newforms/widgets.py:231
#: oldforms/__init__.py:592
msgid "Unknown"
msgstr "Desconegut"
#: contrib/admin/models.py:17
#: contrib/admin/models.py:18
msgid "action time"
msgstr "moment de l'acció"
#: contrib/admin/models.py:20
#: contrib/admin/models.py:21
msgid "object id"
msgstr "id del objecte"
#: contrib/admin/models.py:21
#: contrib/admin/models.py:22
msgid "object repr"
msgstr "'repr' de l'objecte"
#: contrib/admin/models.py:22
#: contrib/admin/models.py:23
msgid "action flag"
msgstr "marca de l'acció"
#: contrib/admin/models.py:23
#: contrib/admin/models.py:24
msgid "change message"
msgstr "missatge del canvi"
#: contrib/admin/models.py:26
#: contrib/admin/models.py:27
msgid "log entry"
msgstr "entrada del registre"
#: contrib/admin/models.py:27
#: contrib/admin/models.py:28
msgid "log entries"
msgstr "entrades del registre"
@ -469,7 +469,7 @@ msgid "Password:"
msgstr "Contrasenya:"
#: contrib/admin/templates/admin/login.html:25
#: contrib/admin/views/decorators.py:24
#: contrib/admin/views/decorators.py:25
msgid "Log in"
msgstr "Iniciar sessió"
@ -769,17 +769,17 @@ msgstr "Actualment:"
msgid "Change:"
msgstr "Modificar:"
#: contrib/admin/templatetags/admin_list.py:254
#: contrib/admin/templatetags/admin_list.py:257
msgid "All dates"
msgstr "Totes les dates"
#: contrib/admin/views/auth.py:20 contrib/admin/views/main.py:264
#: contrib/admin/views/auth.py:20 contrib/admin/views/main.py:267
#, python-format
msgid "The %(name)s \"%(obj)s\" was added successfully."
msgstr "El/la %(name)s \"%(obj)s\".ha estat agregat/da amb èxit."
#: contrib/admin/views/auth.py:25 contrib/admin/views/main.py:268
#: contrib/admin/views/main.py:354
#: contrib/admin/views/auth.py:25 contrib/admin/views/main.py:271
#: contrib/admin/views/main.py:356
msgid "You may edit it again below."
msgstr "Pot editar-lo de nou abaix."
@ -796,7 +796,7 @@ msgstr "Canvi de clau exitós"
msgid "Change password: %s"
msgstr "Canviar clau: %s"
#: contrib/admin/views/decorators.py:10 contrib/auth/forms.py:60
#: contrib/admin/views/decorators.py:11 contrib/auth/forms.py:60
msgid ""
"Please enter a correct username and password. Note that both fields are case-"
"sensitive."
@ -804,7 +804,7 @@ msgstr ""
"Si us plau, introdueixi un nom d'usuari i contrasenya vàlids. Tingui en "
"compte que tots dos camps son sensibles a majúscules i minúscules."
#: contrib/admin/views/decorators.py:62
#: contrib/admin/views/decorators.py:63
msgid ""
"Please log in again, because your session has expired. Don't worry: Your "
"submission has been saved."
@ -812,7 +812,7 @@ msgstr ""
"Si us plau, identifiquis de nou doncs la seva sessió ha expirat. No es "
"preocupi, el seu enviament està emmagatzemat."
#: contrib/admin/views/decorators.py:69
#: contrib/admin/views/decorators.py:70
msgid ""
"Looks like your browser isn't configured to accept cookies. Please enable "
"cookies, reload this page, and try again."
@ -821,247 +821,247 @@ msgstr ""
"'cookies' (galetes). Si us plau, habiliti les 'cookies', recarregui aquesta "
"pàgina i provi-ho de nou. "
#: contrib/admin/views/decorators.py:83
#: contrib/admin/views/decorators.py:84
msgid "Usernames cannot contain the '@' character."
msgstr "Els noms d'usuari no poden contenir el caracter '@'."
#: contrib/admin/views/decorators.py:85
#: contrib/admin/views/decorators.py:86
#, python-format
msgid "Your e-mail address is not your username. Try '%s' instead."
msgstr ""
"La seva adreça de correu no és el seu nom d'usuari. Provi '%s' en tot cas."
#: contrib/admin/views/doc.py:47 contrib/admin/views/doc.py:49
#: contrib/admin/views/doc.py:51
#: contrib/admin/views/doc.py:48 contrib/admin/views/doc.py:50
#: contrib/admin/views/doc.py:52
msgid "tag:"
msgstr "etiqueta:"
#: contrib/admin/views/doc.py:78 contrib/admin/views/doc.py:80
#: contrib/admin/views/doc.py:82
#: contrib/admin/views/doc.py:79 contrib/admin/views/doc.py:81
#: contrib/admin/views/doc.py:83
msgid "filter:"
msgstr "filtre:"
#: contrib/admin/views/doc.py:136 contrib/admin/views/doc.py:138
#: contrib/admin/views/doc.py:140
#: contrib/admin/views/doc.py:137 contrib/admin/views/doc.py:139
#: contrib/admin/views/doc.py:141
msgid "view:"
msgstr "vista:"
#: contrib/admin/views/doc.py:165
#: contrib/admin/views/doc.py:166
#, python-format
msgid "App %r not found"
msgstr "La aplicació %r no s'ha pogut trobar"
#: contrib/admin/views/doc.py:172
#: contrib/admin/views/doc.py:173
#, python-format
msgid "Model %(name)r not found in app %(label)r"
msgstr "El model %(name)r no s'ha trobat en la aplicació %(label)r"
#: contrib/admin/views/doc.py:184
#: contrib/admin/views/doc.py:185
#, python-format
msgid "the related `%(label)s.%(type)s` object"
msgstr "el objecte relacionat `%(label)s.%(type)s`"
#: contrib/admin/views/doc.py:184 contrib/admin/views/doc.py:206
#: contrib/admin/views/doc.py:220 contrib/admin/views/doc.py:225
#: contrib/admin/views/doc.py:185 contrib/admin/views/doc.py:207
#: contrib/admin/views/doc.py:221 contrib/admin/views/doc.py:226
msgid "model:"
msgstr "model:"
#: contrib/admin/views/doc.py:215
#: contrib/admin/views/doc.py:216
#, python-format
msgid "related `%(label)s.%(name)s` objects"
msgstr "objectes relacionats `%(label)s.%(name)s`"
#: contrib/admin/views/doc.py:220
#: contrib/admin/views/doc.py:221
#, python-format
msgid "all %s"
msgstr "tots %s"
#: contrib/admin/views/doc.py:225
#: contrib/admin/views/doc.py:226
#, python-format
msgid "number of %s"
msgstr "nombre de %s"
#: contrib/admin/views/doc.py:230
#: contrib/admin/views/doc.py:231
#, python-format
msgid "Fields on %s objects"
msgstr "Camps en objectes %s"
#: contrib/admin/views/doc.py:292 contrib/admin/views/doc.py:303
#: contrib/admin/views/doc.py:305 contrib/admin/views/doc.py:311
#: contrib/admin/views/doc.py:312 contrib/admin/views/doc.py:314
#: contrib/admin/views/doc.py:293 contrib/admin/views/doc.py:304
#: contrib/admin/views/doc.py:306 contrib/admin/views/doc.py:312
#: contrib/admin/views/doc.py:313 contrib/admin/views/doc.py:315
msgid "Integer"
msgstr "Enter"
#: contrib/admin/views/doc.py:293
#: contrib/admin/views/doc.py:294
msgid "Boolean (Either True or False)"
msgstr "Booleà (Verdader o Fals)"
#: contrib/admin/views/doc.py:294 contrib/admin/views/doc.py:313
#: contrib/admin/views/doc.py:295 contrib/admin/views/doc.py:314
#, python-format
msgid "String (up to %(max_length)s)"
msgstr "Cadena (de fins a %(max_length)s)"
#: contrib/admin/views/doc.py:295
#: contrib/admin/views/doc.py:296
msgid "Comma-separated integers"
msgstr "Enters separats per comes"
#: contrib/admin/views/doc.py:296
#: contrib/admin/views/doc.py:297
msgid "Date (without time)"
msgstr "Data (sense hora)"
#: contrib/admin/views/doc.py:297
#: contrib/admin/views/doc.py:298
msgid "Date (with time)"
msgstr "Data (amb hora)"
#: contrib/admin/views/doc.py:298
#: contrib/admin/views/doc.py:299
msgid "Decimal number"
msgstr "Número decimal"
#: contrib/admin/views/doc.py:299
#: contrib/admin/views/doc.py:300
msgid "E-mail address"
msgstr "Adreça de correu electrònic"
#: contrib/admin/views/doc.py:300 contrib/admin/views/doc.py:301
#: contrib/admin/views/doc.py:304
#: contrib/admin/views/doc.py:301 contrib/admin/views/doc.py:302
#: contrib/admin/views/doc.py:305
msgid "File path"
msgstr "Ruta del fitxer"
#: contrib/admin/views/doc.py:302
#: contrib/admin/views/doc.py:303
msgid "Floating point number"
msgstr "Número amb punt de coma flotant"
#: contrib/admin/views/doc.py:306 contrib/comments/models.py:85
#: contrib/admin/views/doc.py:307 contrib/comments/models.py:85
msgid "IP address"
msgstr "Adreça IP"
#: contrib/admin/views/doc.py:308
#: contrib/admin/views/doc.py:309
msgid "Boolean (Either True, False or None)"
msgstr "Booleà (Verdader, Fals o 'None' (cap))"
#: contrib/admin/views/doc.py:309
#: contrib/admin/views/doc.py:310
msgid "Relation to parent model"
msgstr "Relació amb el model pare"
#: contrib/admin/views/doc.py:310
#: contrib/admin/views/doc.py:311
msgid "Phone number"
msgstr "Número de telèfon"
#: contrib/admin/views/doc.py:315
#: contrib/admin/views/doc.py:316
msgid "Text"
msgstr "Texte"
#: contrib/admin/views/doc.py:316
#: contrib/admin/views/doc.py:317
msgid "Time"
msgstr "Hora"
#: contrib/admin/views/doc.py:317 contrib/flatpages/models.py:7
#: contrib/admin/views/doc.py:318 contrib/flatpages/models.py:7
msgid "URL"
msgstr "URL"
#: contrib/admin/views/doc.py:318
#: contrib/admin/views/doc.py:319
msgid "U.S. state (two uppercase letters)"
msgstr "Estat dels E.U.A. (dos lletres majúscules)"
#: contrib/admin/views/doc.py:319
#: contrib/admin/views/doc.py:320
msgid "XML text"
msgstr "Texte XML"
#: contrib/admin/views/doc.py:345
#: contrib/admin/views/doc.py:346
#, python-format
msgid "%s does not appear to be a urlpattern object"
msgstr "%s no sembla ser un objecte 'urlpattern'"
#: contrib/admin/views/main.py:230
#: contrib/admin/views/main.py:233
msgid "Site administration"
msgstr "Lloc administratiu"
#: contrib/admin/views/main.py:278 contrib/admin/views/main.py:363
#: contrib/admin/views/main.py:280 contrib/admin/views/main.py:365
#, python-format
msgid "You may add another %s below."
msgstr "Pot afegir un altre %s a baix."
#: contrib/admin/views/main.py:296
#: contrib/admin/views/main.py:298
#, python-format
msgid "Add %s"
msgstr "Afegir %s"
#: contrib/admin/views/main.py:342
#: contrib/admin/views/main.py:344
#, python-format
msgid "Added %s."
msgstr "Agregat %s."
#: contrib/admin/views/main.py:342 contrib/admin/views/main.py:344
#: contrib/admin/views/main.py:346 core/validators.py:283
#: contrib/admin/views/main.py:344 contrib/admin/views/main.py:346
#: contrib/admin/views/main.py:348 core/validators.py:283
#: db/models/manipulators.py:309
msgid "and"
msgstr "i"
#: contrib/admin/views/main.py:344
#: contrib/admin/views/main.py:346
#, python-format
msgid "Changed %s."
msgstr "Modificat %s."
#: contrib/admin/views/main.py:346
#: contrib/admin/views/main.py:348
#, python-format
msgid "Deleted %s."
msgstr "Eliminat %s."
#: contrib/admin/views/main.py:349
#: contrib/admin/views/main.py:351
msgid "No fields changed."
msgstr "Cap camp canviat."
#: contrib/admin/views/main.py:352
#: contrib/admin/views/main.py:354
#, python-format
msgid "The %(name)s \"%(obj)s\" was changed successfully."
msgstr "S'ha modificat amb èxist el/la %(name)s \"%(obj)s."
#: contrib/admin/views/main.py:360
#: contrib/admin/views/main.py:362
#, python-format
msgid ""
"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
msgstr ""
"S'ha agregat amb èxit el/la %(name)s \"%(obj)s\". Pot editar-lo de nou abaix."
#: contrib/admin/views/main.py:398
#: contrib/admin/views/main.py:400
#, python-format
msgid "Change %s"
msgstr "Modificar %s"
#: contrib/admin/views/main.py:483
#: contrib/admin/views/main.py:487
#, python-format
msgid "One or more %(fieldname)s in %(name)s: %(obj)s"
msgstr "Un o més %(fieldname)s en %(name)s: %(obj)s"
#: contrib/admin/views/main.py:488
#: contrib/admin/views/main.py:492
#, python-format
msgid "One or more %(fieldname)s in %(name)s:"
msgstr "Un o més %(fieldname)s en %(name)s:"
#: contrib/admin/views/main.py:520
#: contrib/admin/views/main.py:524
#, python-format
msgid "The %(name)s \"%(obj)s\" was deleted successfully."
msgstr "El/la %(name)s \"%(obj)s\".ha estat eliminat amb èxit."
#: contrib/admin/views/main.py:523
#: contrib/admin/views/main.py:527
msgid "Are you sure?"
msgstr "Està segur?"
#: contrib/admin/views/main.py:545
#: contrib/admin/views/main.py:549
#, python-format
msgid "Change history: %s"
msgstr "Modificar històric: %s"
#: contrib/admin/views/main.py:579
#: contrib/admin/views/main.py:583
#, python-format
msgid "Select %s"
msgstr "Seleccioni %s"
#: contrib/admin/views/main.py:579
#: contrib/admin/views/main.py:583
#, python-format
msgid "Select %s to change"
msgstr "Seleccioni %s per modificar"
#: contrib/admin/views/main.py:780
#: contrib/admin/views/main.py:784
msgid "Database error"
msgstr "Error de/en la base de dades"
@ -1622,72 +1622,72 @@ msgstr "n"
msgid "rd"
msgstr "r"
#: contrib/humanize/templatetags/humanize.py:50
#: contrib/humanize/templatetags/humanize.py:52
#, python-format
msgid "%(value).1f million"
msgid_plural "%(value).1f million"
msgstr[0] "%(value).1f milió"
msgstr[1] "%(value).1f milions"
#: contrib/humanize/templatetags/humanize.py:53
#: contrib/humanize/templatetags/humanize.py:55
#, python-format
msgid "%(value).1f billion"
msgid_plural "%(value).1f billion"
msgstr[0] "%(value).1f bilió"
msgstr[1] "%(value).1f bilions"
#: contrib/humanize/templatetags/humanize.py:56
#: contrib/humanize/templatetags/humanize.py:58
#, python-format
msgid "%(value).1f trillion"
msgid_plural "%(value).1f trillion"
msgstr[0] "%(value).1f trilió"
msgstr[1] "%(value).1f trilions"
#: contrib/humanize/templatetags/humanize.py:71
#: contrib/humanize/templatetags/humanize.py:74
msgid "one"
msgstr "un"
#: contrib/humanize/templatetags/humanize.py:71
#: contrib/humanize/templatetags/humanize.py:74
msgid "two"
msgstr "dos"
#: contrib/humanize/templatetags/humanize.py:71
#: contrib/humanize/templatetags/humanize.py:74
msgid "three"
msgstr "tres"
#: contrib/humanize/templatetags/humanize.py:71
#: contrib/humanize/templatetags/humanize.py:74
msgid "four"
msgstr "cuatre"
#: contrib/humanize/templatetags/humanize.py:71
#: contrib/humanize/templatetags/humanize.py:74
msgid "five"
msgstr "cinc"
#: contrib/humanize/templatetags/humanize.py:71
#: contrib/humanize/templatetags/humanize.py:74
msgid "six"
msgstr "sis"
#: contrib/humanize/templatetags/humanize.py:71
#: contrib/humanize/templatetags/humanize.py:74
msgid "seven"
msgstr "set"
#: contrib/humanize/templatetags/humanize.py:71
#: contrib/humanize/templatetags/humanize.py:74
msgid "eight"
msgstr "vuit"
#: contrib/humanize/templatetags/humanize.py:71
#: contrib/humanize/templatetags/humanize.py:74
msgid "nine"
msgstr "nou"
#: contrib/humanize/templatetags/humanize.py:90
#: contrib/humanize/templatetags/humanize.py:94
msgid "today"
msgstr "avui"
#: contrib/humanize/templatetags/humanize.py:92
#: contrib/humanize/templatetags/humanize.py:96
msgid "tomorrow"
msgstr "demà"
#: contrib/humanize/templatetags/humanize.py:94
#: contrib/humanize/templatetags/humanize.py:98
msgid "yesterday"
msgstr "ahir"
@ -3024,6 +3024,50 @@ msgstr ""
"Introdueixi un número vàlid de la Seguretat Social dels E.U.A. en el format "
"XXX-XX-XXXX."
#: contrib/localflavor/za/forms.py:22
msgid "Enter a valid South African ID number"
msgstr "Introdueixi un número d'Identitat Sud Africà valid"
#: contrib/localflavor/za/forms.py:57
msgid "Enter a valid South African postal code"
msgstr "Introdueixi un codi postal Sud Africà vàlid."
#: contrib/localflavor/za/za_provinces.py:4
msgid "Eastern Cape"
msgstr "Eastern Cape"
#: contrib/localflavor/za/za_provinces.py:5
msgid "Free State"
msgstr "Free State"
#: contrib/localflavor/za/za_provinces.py:6
msgid "Gauteng"
msgstr "Gauteng"
#: contrib/localflavor/za/za_provinces.py:7
msgid "KwaZulu-Natal"
msgstr "KwaZulu-Natal"
#: contrib/localflavor/za/za_provinces.py:8
msgid "Limpopo"
msgstr "Limpopo"
#: contrib/localflavor/za/za_provinces.py:9
msgid "Mpumalanga"
msgstr "Mpumalanga"
#: contrib/localflavor/za/za_provinces.py:10
msgid "Northern Cape"
msgstr "Northern Cape"
#: contrib/localflavor/za/za_provinces.py:11
msgid "North West"
msgstr "North West"
#: contrib/localflavor/za/za_provinces.py:12
msgid "Western Cape"
msgstr "Western Cape"
#: contrib/redirects/models.py:7
msgid "redirect from"
msgstr "redreçar des de"
@ -3056,23 +3100,23 @@ msgstr "redreçament"
msgid "redirects"
msgstr "redreçaments"
#: contrib/sessions/models.py:80
#: contrib/sessions/models.py:46
msgid "session key"
msgstr "clau de la sessió"
#: contrib/sessions/models.py:81
#: contrib/sessions/models.py:47
msgid "session data"
msgstr "dades de la sessió"
#: contrib/sessions/models.py:82
#: contrib/sessions/models.py:48
msgid "expire date"
msgstr "data de caducitat"
#: contrib/sessions/models.py:87
#: contrib/sessions/models.py:53
msgid "session"
msgstr "sessió"
#: contrib/sessions/models.py:88
#: contrib/sessions/models.py:54
msgid "sessions"
msgstr "sessions"
@ -3141,7 +3185,7 @@ msgstr "No s'admeten caracters no numèrics."
msgid "This value can't be comprised solely of digits."
msgstr "Aquest valor no pot contenir només dígits."
#: core/validators.py:128 newforms/fields.py:157
#: core/validators.py:128 newforms/fields.py:151
msgid "Enter a whole number."
msgstr "Introdueixi un número sencer."
@ -3170,17 +3214,17 @@ msgstr "Introdueixi una hora vàlida en el format HH:MM."
msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format."
msgstr "Introdueixi un data/hora vàlida en format YYYY-MM-DD HH:MM."
#: core/validators.py:170 newforms/fields.py:408
#: core/validators.py:170 newforms/fields.py:402
msgid "Enter a valid e-mail address."
msgstr "Introdueixi una adreça de correu vàlida."
#: core/validators.py:182 core/validators.py:474 newforms/fields.py:438
#: oldforms/__init__.py:686
#: core/validators.py:182 core/validators.py:474 newforms/fields.py:432
#: oldforms/__init__.py:687
msgid "No file was submitted. Check the encoding type on the form."
msgstr ""
"No s'ha enviat cap fitxer. Comprovi el tipus de codificació del formulari."
#: core/validators.py:193 newforms/fields.py:462
#: core/validators.py:193 newforms/fields.py:456
msgid ""
"Upload a valid image. The file you uploaded was either not an image or a "
"corrupted image."
@ -3431,7 +3475,7 @@ msgstr "Ja existeix %(optname)s amb auqest %(fieldname)s."
#: db/models/fields/__init__.py:161 db/models/fields/__init__.py:318
#: db/models/fields/__init__.py:735 db/models/fields/__init__.py:746
#: newforms/fields.py:45 newforms/models.py:211 oldforms/__init__.py:373
#: newforms/fields.py:45 oldforms/__init__.py:374
msgid "This field is required."
msgstr "Aquest camp és obligatori."
@ -3484,150 +3528,150 @@ msgstr[1] ""
msgid "Enter a valid value."
msgstr "Introdueixi un valor vàlid."
#: newforms/fields.py:129
#: newforms/fields.py:123
#, python-format
msgid "Ensure this value has at most %(max)d characters (it has %(length)d)."
msgstr ""
"Asseguris de que el valor té com a màxim %(max)d caràcters (en té %(length)"
"d)."
#: newforms/fields.py:130
#: newforms/fields.py:124
#, python-format
msgid "Ensure this value has at least %(min)d characters (it has %(length)d)."
msgstr ""
"Asseguris de que el valor té com a mínim %(min)d caràcters (en té %(length)"
"d)."
#: newforms/fields.py:158 newforms/fields.py:187 newforms/fields.py:216
#: newforms/fields.py:152 newforms/fields.py:181 newforms/fields.py:210
#, python-format
msgid "Ensure this value is less than or equal to %s."
msgstr "Aquest valor ha de ser menor o igual a %s."
#: newforms/fields.py:159 newforms/fields.py:188 newforms/fields.py:217
#: newforms/fields.py:153 newforms/fields.py:182 newforms/fields.py:211
#, python-format
msgid "Ensure this value is greater than or equal to %s."
msgstr "Asseguris de que aquest valor sigui superior o igual a %s."
#: newforms/fields.py:186 newforms/fields.py:215
#: newforms/fields.py:180 newforms/fields.py:209
msgid "Enter a number."
msgstr "Introdueixi un número."
#: newforms/fields.py:218
#: newforms/fields.py:212
#, python-format
msgid "Ensure that there are no more than %s digits in total."
msgstr "Asseguris de que no hi ha més de %s dígits en total."
#: newforms/fields.py:219
#: newforms/fields.py:213
#, python-format
msgid "Ensure that there are no more than %s decimal places."
msgstr "Asseguris de que no hi ha més de %s decimals."
#: newforms/fields.py:220
#: newforms/fields.py:214
#, python-format
msgid "Ensure that there are no more than %s digits before the decimal point."
msgstr "Asseguris de que no hia ha més de %s dígits decimals."
#: newforms/fields.py:268 newforms/fields.py:724
#: newforms/fields.py:262 newforms/fields.py:719
msgid "Enter a valid date."
msgstr "Introdueixi una data vàlida."
#: newforms/fields.py:301 newforms/fields.py:725
#: newforms/fields.py:295 newforms/fields.py:720
msgid "Enter a valid time."
msgstr "Introdueixi una hora vàlida."
#: newforms/fields.py:340
#: newforms/fields.py:334
msgid "Enter a valid date/time."
msgstr "Introdueixi una data/hora vàlides."
#: newforms/fields.py:439
#: newforms/fields.py:433
msgid "No file was submitted."
msgstr "No s'ha enviat cap fitxer."
#: newforms/fields.py:440 oldforms/__init__.py:688
#: newforms/fields.py:434 oldforms/__init__.py:689
msgid "The submitted file is empty."
msgstr "El fitxer enviat està buit."
#: newforms/fields.py:498
#: newforms/fields.py:492
msgid "Enter a valid URL."
msgstr "Introdueixi una URL vàlida."
#: newforms/fields.py:499
#: newforms/fields.py:493
msgid "This URL appears to be a broken link."
msgstr "Aquesta URL sembla ser un enllaç trencat."
#: newforms/fields.py:560 newforms/models.py:194
#: newforms/fields.py:555 newforms/models.py:155
msgid "Select a valid choice. That choice is not one of the available choices."
msgstr ""
"Esculli una opció vàlida; Aquesta opció no és una de les opcions disponibles."
#: newforms/fields.py:599
#: newforms/fields.py:594
#, python-format
msgid "Select a valid choice. %(value)s is not one of the available choices."
msgstr "Esculli una opció vàlida. %(value)s no és una de les opcions vàlides."
#: newforms/fields.py:600 newforms/fields.py:662 newforms/models.py:215
#: newforms/fields.py:595 newforms/fields.py:657 newforms/models.py:215
msgid "Enter a list of values."
msgstr "Introdueixi una llista de valors."
#: newforms/fields.py:753
#: newforms/fields.py:748
msgid "Enter a valid IPv4 address."
msgstr "Introdueixi una adreça IPv4 vàlida."
#: newforms/models.py:221
#: newforms/models.py:216
#, python-format
msgid "Select a valid choice. %s is not one of the available choices."
msgstr "Esculli una opció vàlida; %s' no és una de les opcions vàlides."
#: oldforms/__init__.py:408
#: oldforms/__init__.py:409
#, python-format
msgid "Ensure your text is less than %s character."
msgid_plural "Ensure your text is less than %s characters."
msgstr[0] "Asseguris de que el seu texte té menys de %s caracter."
msgstr[1] "Asseguris de que el seu texte té menys de %s caracters."
#: oldforms/__init__.py:413
#: oldforms/__init__.py:414
msgid "Line breaks are not allowed here."
msgstr "No es permeten salts de línia."
#: oldforms/__init__.py:511 oldforms/__init__.py:585 oldforms/__init__.py:624
#: oldforms/__init__.py:512 oldforms/__init__.py:586 oldforms/__init__.py:625
#, python-format
msgid "Select a valid choice; '%(data)s' is not in %(choices)s."
msgstr "Esculli una opció vàlida; %(data)s' no està dintre de %(choices)s."
#: oldforms/__init__.py:744
#: oldforms/__init__.py:745
msgid "Enter a whole number between -32,768 and 32,767."
msgstr "Introdueixi un número enter entre -32,768 i 32,767."
#: oldforms/__init__.py:754
#: oldforms/__init__.py:755
msgid "Enter a positive number."
msgstr "Introdueixi un número positiu."
#: oldforms/__init__.py:764
#: oldforms/__init__.py:765
msgid "Enter a whole number between 0 and 32,767."
msgstr "Introdueixi un número entre 0 i 32,767."
#: template/defaultfilters.py:555
#: template/defaultfilters.py:658
msgid "yes,no,maybe"
msgstr "si,no,potser"
#: template/defaultfilters.py:585
#: template/defaultfilters.py:689
#, python-format
msgid "%(size)d byte"
msgid_plural "%(size)d bytes"
msgstr[0] "%(size)d byte"
msgstr[1] "%(size)d bytes"
#: template/defaultfilters.py:587
#: template/defaultfilters.py:691
#, python-format
msgid "%.1f KB"
msgstr "%.1f KB"
#: template/defaultfilters.py:589
#: template/defaultfilters.py:693
#, python-format
msgid "%.1f MB"
msgstr "%.1f MB"
#: template/defaultfilters.py:590
#: template/defaultfilters.py:694
#, python-format
msgid "%.1f GB"
msgstr "%.1f GB"
@ -3890,23 +3934,23 @@ msgstr "%(number)d %(type)s"
msgid ", %(number)d %(type)s"
msgstr ", %(number)d %(type)s"
#: utils/translation/trans_real.py:395
#: utils/translation/trans_real.py:399
msgid "DATE_FORMAT"
msgstr "F j, Y"
#: utils/translation/trans_real.py:396
#: utils/translation/trans_real.py:400
msgid "DATETIME_FORMAT"
msgstr "F j, Y, H:i"
#: utils/translation/trans_real.py:397
#: utils/translation/trans_real.py:401
msgid "TIME_FORMAT"
msgstr "H:i"
#: utils/translation/trans_real.py:413
#: utils/translation/trans_real.py:417
msgid "YEAR_MONTH_FORMAT"
msgstr "j de/d' F del Y"
#: utils/translation/trans_real.py:414
#: utils/translation/trans_real.py:418
msgid "MONTH_DAY_FORMAT"
msgstr "j de/d' F del Y"
@ -3924,43 +3968,3 @@ msgstr "El/La %(verbose_name)s s'ha actualtzat amb èxit."
#, python-format
msgid "The %(verbose_name)s was deleted."
msgstr "El %(verbose_name)s s'ha eliminat."
#~ msgid ""
#~ "This comment was posted by a user who has posted fewer than %(count)s "
#~ "comment:\n"
#~ "\n"
#~ "%(text)sThis comment was posted by a user who has posted fewer than %"
#~ "(count)s comments:\n"
#~ "\n"
#~ "%(text)s"
#~ msgstr ""
#~ "Aquest comentari el va enviar un usuari que ha enviat menys de %(count)s "
#~ "comentari:\n"
#~ "\n"
#~ "%(text)sAquest comentari el va enviar un usuari que ha enviat menys de %"
#~ "(count)s comentaris:\n"
#~ "\n"
#~ "%(text)s"
#~ msgid "AnonymousUser"
#~ msgstr "AnonymousUser"
#~ msgid ""
#~ "Please enter a valid decimal number with a whole part of at most %s digit."
#~ "Please enter a valid decimal number with a whole part of at most %s "
#~ "digits."
#~ msgstr ""
#~ "Si us plau, introdueixi un número decimal vàlid amb la part entera amb "
#~ "com a màxim %s dígit.Si us plau, introdueixi un número decimal vàlid amb "
#~ "la part entera amb com a màxim %s dígits."
#~ msgid ""
#~ "Please enter a valid decimal number with at most %s decimal place.Please "
#~ "enter a valid decimal number with at most %s decimal places."
#~ msgstr ""
#~ "Si us plau, introdueixi un número decimal vàlid amb no més de %s dígit en "
#~ "la part decimal.Si us plau, introdueixi un número decimal vàlid amb no "
#~ "més de %s dígits en la part decimal."
#~ msgid "%d milliseconds"
#~ msgstr "%d milisegons"

View File

@ -1,17 +1,12 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the django package.
# Johan C. Stöver <johan@nilling.nl>, 2005.
# Rudolph Froger <rfroger@estrate.nl>, 2006.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: Django 1.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2006-12-09 15:51+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Johan C. Stöver <johan@nilling.nl>\n"
"PO-Revision-Date: 2007-12-17 21:14+0100\n"
"Last-Translator: I.S. van Oostveen\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
@ -69,7 +64,7 @@ msgstr "De waarde moet een geheel getal zijn."
#: db/models/fields/__init__.py:381
msgid "This value must be either True or False."
msgstr "De waarde moet of True (waar) of False (onwaar) zijn."
msgstr "De waarde moet of True (Waar) of False (Onwaar) zijn."
#: db/models/fields/__init__.py:397
msgid "This field cannot be null."
@ -279,7 +274,7 @@ msgstr "Alleen alfabetische karakters zijn toegestaan"
#: core/validators.py:139
msgid "Year must be 1900 or later."
msgstr "Het jaartal moet 1900 of nieuwer zijn."
msgstr "Het jaartal moet 1900 of later zijn."
#: core/validators.py:143
#, python-format
@ -296,20 +291,20 @@ msgstr "Geef een geldig e-mailadres op."
#: 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 "Er was geen bestand verstuurd. Controleer de encoding van het formulier."
msgstr "Er was geen bestand verstuurd. Controleer het coderings type van het formulier."
#: core/validators.py:177
msgid ""
"Upload a valid image. The file you uploaded was either not an image or a "
"corrupted image."
msgstr ""
"Bestand ongeldig. Het bestand dat is gegeven is geen afbeelding of was "
"Bestand ongeldig. Het bestand dat is gegeven is geen afbeelding of is "
"beschadigd."
#: core/validators.py:184
#, python-format
msgid "The URL %s does not point to a valid image."
msgstr "De URL %s wijst niet naar een afbeelding."
msgstr "De URL %s wijst niet naar een geldige afbeelding."
#: core/validators.py:188
#, python-format
@ -321,7 +316,7 @@ msgstr ""
#: core/validators.py:196
#, python-format
msgid "The URL %s does not point to a valid QuickTime video."
msgstr "De URL %s wijst niet naar een QuickTime video."
msgstr "De URL %s wijst niet naar een geldige QuickTime video."
#: core/validators.py:200
msgid "A valid URL is required."
@ -349,18 +344,18 @@ msgstr "Ongeldige URL: %s"
#: core/validators.py:243 core/validators.py:245
#, python-format
msgid "The URL %s is a broken link."
msgstr "De URL %s is een niet werkende link."
msgstr "De URL %s is niet een werkende link."
#: core/validators.py:251
msgid "Enter a valid U.S. state abbreviation."
msgstr "Geef een geldige afkorting van een VS staat."
msgstr "Geef een geldige afkorting van een staat in de VS."
#: 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] "Pas op uw taalgebruik! Gebruik van %s niet toegestaan."
msgstr[1] "Pas op uw taalgebruik! Gebruik van de woorden %s niet toegestaan."
msgstr[1] "Pas op uw taalgebruik! Gebruik van de woorden %s is niet toegestaan."
#: core/validators.py:272
#, python-format
@ -373,7 +368,7 @@ msgstr "Voer tenminste één veld in."
#: core/validators.py:300 core/validators.py:311
msgid "Please enter both fields or leave them both empty."
msgstr "Voer waarden in in beide velden of laat beide leeg."
msgstr "Voer waarden in beide velden in of laat beide leeg."
#: core/validators.py:318
#, python-format
@ -450,7 +445,7 @@ msgstr "Zorg ervoor dat het bestand hoogstens %s bytes groot is."
#: core/validators.py:453
msgid "The format for this field is wrong."
msgstr "Het formaat van dit veld is fout."
msgstr "Het formaat van dit veld is foutief."
#: core/validators.py:468
msgid "This field is invalid."
@ -536,7 +531,7 @@ msgid ""
"Your Web browser doesn't appear to have cookies enabled. Cookies are "
"required for logging in."
msgstr ""
"Het lijkt erop dat uw browser geen cookies accepteerd. Om aan te melden "
"Het lijkt erop dat uw browser geen cookies accepteert. Om aan te melden "
"moeten cookies worden geaccepteerd."
#: contrib/auth/forms.py:59 contrib/admin/views/decorators.py:10
@ -645,7 +640,7 @@ msgstr "supergebruiker status"
msgid ""
"Designates that this user has all permissions without explicitly assigning "
"them."
msgstr "Bepaald dat deze gebruiker alle rechten heeft, zonder deze expliciet toe te wijzen."
msgstr "Bepaalt dat deze gebruiker alle rechten heeft, zonder deze expliciet toe te wijzen."
#: contrib/auth/models.py:98
msgid "last login"
@ -685,7 +680,7 @@ msgstr "Rechten"
#: contrib/auth/models.py:113
msgid "Important dates"
msgstr "Belangrijke data"
msgstr "Belangrijke datums"
#: contrib/auth/models.py:114
msgid "Groups"
@ -783,7 +778,7 @@ msgid ""
"Please log in again, because your session has expired. Don't worry: Your "
"submission has been saved."
msgstr ""
"Uw sessie is verlopen, meldt u opnieuw aan. Maakt u geen zorgen: Uw bijdrage "
"Uw sessie is verlopen, meld u opnieuw aan. Maakt u zich geen zorgen: Uw bijdrage "
"is opgeslagen."
#: contrib/admin/views/decorators.py:69
@ -791,7 +786,7 @@ msgid ""
"Looks like your browser isn't configured to accept cookies. Please enable "
"cookies, reload this page, and try again."
msgstr ""
"Het lijkt erop dat uw browser geen cookies accepteerd. Zet het gebruik van "
"Het lijkt erop dat uw browser geen cookies accepteert. Zet het gebruik van "
"cookies aan in uw browser, laad deze pagina nogmaals en probeer het opnieuw."
#: contrib/admin/views/decorators.py:83
@ -928,7 +923,7 @@ msgstr "Model %r niet gevonden in app %r"
#: contrib/admin/views/doc.py:183
#, python-format
msgid "the related `%s.%s` object"
msgstr "the related `%s.%s` object"
msgstr "het gerelateerde `%s.%s` object"
#: contrib/admin/views/doc.py:183 contrib/admin/views/doc.py:205
#: contrib/admin/views/doc.py:219 contrib/admin/views/doc.py:224
@ -938,7 +933,7 @@ msgstr "model:"
#: contrib/admin/views/doc.py:214
#, python-format
msgid "related `%s.%s` objects"
msgstr "related `%s.%s` objects"
msgstr "de gerelateerde `%s.%s` objecten"
#: contrib/admin/views/doc.py:219
#, python-format
@ -948,12 +943,12 @@ msgstr "alle %s"
#: contrib/admin/views/doc.py:224
#, python-format
msgid "number of %s"
msgstr "nummer van %s"
msgstr "aantal %s"
#: contrib/admin/views/doc.py:229
#, python-format
msgid "Fields on %s objects"
msgstr "Velden van %s objects"
msgstr "Velden van %s objecten"
#: contrib/admin/views/doc.py:291 contrib/admin/views/doc.py:301
#: contrib/admin/views/doc.py:303 contrib/admin/views/doc.py:309
@ -1139,11 +1134,11 @@ msgid ""
"All of the following related items will be deleted:"
msgstr ""
"Weet u zeker dat u %(object_name)s \"%(escaped_object)s\" wilt verwijderen? Alle "
"volgende opjecten worden verwijderd:"
"volgende objecten worden verwijderd:"
#: contrib/admin/templates/admin/delete_confirmation.html:26
msgid "Yes, I'm sure"
msgstr "Ja, Ik weet het zeker"
msgstr "Ja, ik weet het zeker"
#: contrib/admin/templates/admin/404.html:4
#: contrib/admin/templates/admin/404.html:8
@ -1197,7 +1192,7 @@ msgstr "Opslaan en nieuw item"
#: contrib/admin/templates/admin/submit_line.html:6
msgid "Save and continue editing"
msgstr "Opslaan en bewerk opnieuw"
msgstr "Opslaan en opnieuw bewerken"
#: contrib/admin/templates/admin/submit_line.html:7
msgid "Save"
@ -1224,7 +1219,7 @@ msgstr "Wijzigen"
#: contrib/admin/templates/admin/index.html:44
msgid "You don't have permission to edit anything."
msgstr "U heeft geen rechten om iets te wijzigen"
msgstr "U heeft geen rechten om iets te wijzigen."
#: contrib/admin/templates/admin/index.html:52
msgid "Recent Actions"
@ -1380,7 +1375,7 @@ msgstr ""
"de bookmarklet vanuit elke pagina op de site worden gekozen. Let erop dat "
"het soms\n"
"noodzakelijk is dat de computer van waaruit de pagina wordt bekeken intern "
"is\n"
"is.\n"
"(Raadpleeg uw systeembeheerder of uw computer zich op het interne netwerk "
"bevind).<p>\n"
@ -1393,7 +1388,7 @@ msgid ""
"Jumps you from any page to the documentation for the view that generates "
"that page."
msgstr ""
"Spring vanuit elke pagina naar de documentatie voor de view die gegenereerd "
"Springt vanuit elke pagina naar de documentatie voor de view die gegenereerd "
"wordt door die pagina"
#: contrib/admin/templates/admin_doc/bookmarklets.html:22
@ -1406,7 +1401,7 @@ msgid ""
"object."
msgstr ""
"Toont de content-type en unieke ID voor pagina's die een enkel object "
"voorsteld."
"voorstellen."
#: contrib/admin/templates/admin_doc/bookmarklets.html:25
msgid "Edit this object (current window)"
@ -1414,7 +1409,7 @@ msgstr "Bewerk dit object (huidig venster)"
#: contrib/admin/templates/admin_doc/bookmarklets.html:26
msgid "Jumps to the admin page for pages that represent a single object."
msgstr "Ga naar de beheerpagina voor pagina's die een enkel object weergeven."
msgstr "Gaat naar de beheerpagina voor pagina's die een enkel object weergeven."
#: contrib/admin/templates/admin_doc/bookmarklets.html:28
msgid "Edit this object (new window)"
@ -1527,7 +1522,7 @@ msgid ""
"password twice so we can verify you typed it in correctly."
msgstr ""
"Vanwege de beveiliging moet u uw oude en twee keer een nieuw "
"wachtwoordinvoeren, zodat we kunnen controleren of er geen typefouten zijn "
"wachtwoord invoeren, zodat we kunnen controleren of er geen typefouten zijn "
"gemaakt."
#: contrib/admin/templates/registration/password_change_form.html:17
@ -1597,7 +1592,7 @@ msgid ""
"Example: 'flatpages/contact_page.html'. If this isn't provided, the system "
"will use 'flatpages/default.html'."
msgstr ""
"Voorbeeld: 'flatpages/contact_page'. Als deze niet is opgegeven, dan wordt "
"Voorbeeld: 'flatpages/contact_page.html'. Als deze niet is opgegeven, dan wordt "
"'flatpages/default.html' gebruikt."
#: contrib/flatpages/models.py:14
@ -1894,7 +1889,7 @@ msgstr "Een of meerdere verplichte velden zijn niet ingevuld"
#: contrib/comments/views/comments.py:196
#: contrib/comments/views/comments.py:286
msgid "Somebody tampered with the comment form (security violation)"
msgstr "Iemand heeft het opmerkingenformulier gewijzigd (Beveilingsinbreuk)"
msgstr "Iemand heeft het opmerkingenformulier gewijzigd (beveilingsinbreuk)"
#: contrib/comments/views/comments.py:206
#: contrib/comments/views/comments.py:292

View File

@ -55,6 +55,12 @@ var POLISH_MAP = {
'Ź':'Z', 'Ż':'Z'
}
var LATVIAN_MAP = {
'ā':'a', 'č':'c', 'ē':'e', 'ģ':'g', 'ī':'i', 'ķ':'k', 'ļ':'l', 'ņ':'n',
'š':'s', 'ū':'u', 'ž':'z', 'Ā':'A', 'Č':'C', 'Ē':'E', 'Ģ':'G', 'Ī':'i',
'Ķ':'k', 'Ļ':'L', 'Ņ':'N', 'Š':'S', 'Ū':'u', 'Ž':'Z'
}
var ALL_DOWNCODE_MAPS=new Array()
ALL_DOWNCODE_MAPS[0]=LATIN_MAP
ALL_DOWNCODE_MAPS[1]=LATIN_SYMBOLS_MAP
@ -64,6 +70,7 @@ ALL_DOWNCODE_MAPS[4]=RUSSIAN_MAP
ALL_DOWNCODE_MAPS[5]=UKRAINIAN_MAP
ALL_DOWNCODE_MAPS[6]=CZECH_MAP
ALL_DOWNCODE_MAPS[7]=POLISH_MAP
ALL_DOWNCODE_MAPS[8]=LATVIAN_MAP
var Downcoder = new Object();
Downcoder.Initialize = function()

View File

@ -114,7 +114,7 @@ def result_headers(cl):
yield {"text": header,
"sortable": True,
"url": cl.get_query_string({ORDER_VAR: i, ORDER_TYPE_VAR: new_order_type}),
"class_attrib": mark_safe((th_classes and ' class="%s"' % ' '.join(th_classes) or ''))}
"class_attrib": mark_safe(th_classes and ' class="%s"' % ' '.join(th_classes) or '')}
def _boolean_icon(field_val):
BOOLEAN_MAPPING = {True: 'yes', False: 'no', None: 'unknown'}

View File

@ -307,7 +307,7 @@ class AnonymousUser(object):
id = None
username = ''
is_staff = False
is_active = True
is_active = False
is_superuser = False
_groups = EmptyManager()
_user_permissions = EmptyManager()

View File

@ -16,9 +16,21 @@ False
>>> u2 = User.objects.create_user('testuser2', 'test2@example.com')
>>> u2.has_usable_password()
False
>>> u.is_authenticated()
True
>>> u.is_staff
False
>>> u.is_active
True
>>> a = AnonymousUser()
>>> a.is_authenticated()
False
>>> a.is_staff
False
>>> a.is_active
False
>>> a.groups.all()
[]
>>> a.user_permissions.all()

View File

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

View File

@ -12,6 +12,7 @@ from django.utils.safestring import mark_safe
from django.db.models.query import QuerySet
EMPTY_VALUE = '(None)'
DISPLAY_SIZE = 100
class EasyModel(object):
def __init__(self, site, model):
@ -93,8 +94,8 @@ class EasyInstance(object):
def __unicode__(self):
val = smart_unicode(self.instance)
if len(val) > 30:
return val[:30] + u'...'
if len(val) > DISPLAY_SIZE:
return val[:DISPLAY_SIZE] + u'...'
return val
def __str__(self):

View File

@ -24,18 +24,20 @@ class ARPostalCodeField(RegexField):
See http://www.correoargentino.com.ar/consulta_cpa/home.php
"""
default_error_messages = {
'invalid': ugettext("Enter a postal code in the format NNNN or ANNNNAAA."),
}
def __init__(self, *args, **kwargs):
super(ARPostalCodeField, self).__init__(r'^\d{4}$|^[A-HJ-NP-Za-hj-np-z]\d{4}\D{3}$',
min_length=4, max_length=8,
error_message=ugettext("Enter a postal code in the format NNNN or ANNNNAAA."),
*args, **kwargs)
min_length=4, max_length=8, *args, **kwargs)
def clean(self, value):
value = super(ARPostalCodeField, self).clean(value)
if value in EMPTY_VALUES:
return u''
if len(value) not in (4, 8):
raise ValidationError(ugettext("Enter a postal code in the format NNNN or ANNNNAAA."))
raise ValidationError(self.error_messages['invalid'])
if len(value) == 8:
return u'%s%s%s' % (value[0].upper(), value[1:5], value[5:].upper())
return value
@ -44,6 +46,11 @@ class ARDNIField(CharField):
"""
A field that validates `Documento Nacional de Identidad´ (DNI) numbers.
"""
default_error_messages = {
'invalid': ugettext("This field requires only numbers."),
'max_digits': ugettext("This field requires 7 or 8 digits."),
}
def __init__(self, *args, **kwargs):
super(ARDNIField, self).__init__(max_length=10, min_length=7, *args,
**kwargs)
@ -58,10 +65,9 @@ class ARDNIField(CharField):
if not value.isdigit():
value = value.replace('.', '')
if not value.isdigit():
raise ValidationError(ugettext("This field requires only numbers."))
raise ValidationError(self.error_messages['invalid'])
if len(value) not in (7, 8):
raise ValidationError(
ugettext("This field requires 7 or 8 digits."))
raise ValidationError(self.error_messages['max_digits'])
return value
@ -70,9 +76,13 @@ class ARCUITField(RegexField):
This field validates a CUIT (Código Único de Identificación Tributaria). A
CUIT is of the form XX-XXXXXXXX-V. The last digit is a check digit.
"""
default_error_messages = {
'invalid': ugettext('Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.'),
'checksum': ugettext("Invalid CUIT."),
}
def __init__(self, *args, **kwargs):
super(ARCUITField, self).__init__(r'^\d{2}-?\d{8}-?\d$',
error_message=ugettext('Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.'),
*args, **kwargs)
def clean(self, value):
@ -85,7 +95,7 @@ class ARCUITField(RegexField):
return u''
value, cd = self._canon(value)
if self._calc_cd(value) != cd:
raise ValidationError(ugettext("Invalid CUIT."))
raise ValidationError(self.error_messages['checksum'])
return self._format(value, cd)
def _canon(self, cuit):

View File

@ -12,14 +12,20 @@ PHONE_DIGITS_RE = re.compile(r'^(\d{10})$')
class AUPostCodeField(RegexField):
"""Australian post code field."""
default_error_messages = {
'invalid': ugettext('Enter a 4 digit post code.'),
}
def __init__(self, *args, **kwargs):
super(AUPostCodeField, self).__init__(r'^\d{4}$',
max_length=None, min_length=None,
error_message=ugettext('Enter a 4 digit post code.'),
*args, **kwargs)
max_length=None, min_length=None, *args, **kwargs)
class AUPhoneNumberField(Field):
"""Australian phone number field."""
default_error_messages = {
'invalid': u'Phone numbers must contain 10 digits.',
}
def clean(self, value):
"""
Validate a phone number. Strips parentheses, whitespace and hyphens.
@ -31,7 +37,7 @@ class AUPhoneNumberField(Field):
phone_match = PHONE_DIGITS_RE.search(value)
if phone_match:
return u'%s' % phone_match.group(1)
raise ValidationError(u'Phone numbers must contain 10 digits.')
raise ValidationError(self.error_messages['invalid'])
class AUStateSelect(Select):
"""

View File

@ -17,13 +17,19 @@ except NameError:
phone_digits_re = re.compile(r'^(\d{2})[-\.]?(\d{4})[-\.]?(\d{4})$')
class BRZipCodeField(RegexField):
default_error_messages = {
'invalid': _('Enter a zip code in the format XXXXX-XXX.'),
}
def __init__(self, *args, **kwargs):
super(BRZipCodeField, self).__init__(r'^\d{5}-\d{3}$',
max_length=None, min_length=None,
error_message=_('Enter a zip code in the format XXXXX-XXX.'),
*args, **kwargs)
max_length=None, min_length=None, *args, **kwargs)
class BRPhoneNumberField(Field):
default_error_messages = {
'invalid': _('Phone numbers must be in XX-XXXX-XXXX format.'),
}
def clean(self, value):
super(BRPhoneNumberField, self).clean(value)
if value in EMPTY_VALUES:
@ -32,7 +38,7 @@ class BRPhoneNumberField(Field):
m = phone_digits_re.search(value)
if m:
return u'%s-%s-%s' % (m.group(1), m.group(2), m.group(3))
raise ValidationError(_('Phone numbers must be in XX-XXXX-XXXX format.'))
raise ValidationError(self.error_messages['invalid'])
class BRStateSelect(Select):
"""
@ -48,6 +54,9 @@ class BRStateChoiceField(Field):
A choice field that uses a list of Brazilian states as its choices.
"""
widget = Select
default_error_messages = {
'invalid': _(u'Select a valid brazilian state. That state is not one of the available states.'),
}
def __init__(self, required=True, widget=None, label=None,
initial=None, help_text=None):
@ -65,9 +74,7 @@ class BRStateChoiceField(Field):
return value
valid_values = set([smart_unicode(k) for k, v in self.widget.choices])
if value not in valid_values:
raise ValidationError(_(u'Select a valid brazilian state.'
u' That state is not one'
u' of the available states.'))
raise ValidationError(self.error_messages['invalid'])
return value
def DV_maker(v):
@ -83,6 +90,12 @@ class BRCPFField(CharField):
More information:
http://en.wikipedia.org/wiki/Cadastro_de_Pessoas_F%C3%ADsicas
"""
default_error_messages = {
'invalid': _("Invalid CPF number."),
'max_digits': _("This field requires at most 11 digits or 14 characters."),
'digits_only': _("This field requires only numbers."),
}
def __init__(self, *args, **kwargs):
super(BRCPFField, self).__init__(max_length=14, min_length=11, *args, **kwargs)
@ -100,9 +113,9 @@ class BRCPFField(CharField):
try:
int(value)
except ValueError:
raise ValidationError(_("This field requires only numbers."))
raise ValidationError(self.error_messages['digits_only'])
if len(value) != 11:
raise ValidationError(_("This field requires at most 11 digits or 14 characters."))
raise ValidationError(self.error_messages['max_digits'])
orig_dv = value[-2:]
new_1dv = sum([i * int(value[idx]) for idx, i in enumerate(range(10, 1, -1))])
@ -112,11 +125,17 @@ class BRCPFField(CharField):
new_2dv = DV_maker(new_2dv % 11)
value = value[:-1] + str(new_2dv)
if value[-2:] != orig_dv:
raise ValidationError(_("Invalid CPF number."))
raise ValidationError(self.error_messages['invalid'])
return orig_value
class BRCNPJField(Field):
default_error_messages = {
'invalid': _("Invalid CNPJ number."),
'digits_only': _("This field requires only numbers."),
'max_digits': _("This field requires at least 14 digits"),
}
def clean(self, value):
"""
Value can be either a string in the format XX.XXX.XXX/XXXX-XX or a
@ -131,10 +150,9 @@ class BRCNPJField(Field):
try:
int(value)
except ValueError:
raise ValidationError("This field requires only numbers.")
raise ValidationError(self.error_messages['digits_only'])
if len(value) != 14:
raise ValidationError(
_("This field requires at least 14 digits"))
raise ValidationError(self.error_messages['max_digits'])
orig_dv = value[-2:]
new_1dv = sum([i * int(value[idx]) for idx, i in enumerate(range(5, 1, -1) + range(9, 1, -1))])
@ -144,7 +162,6 @@ class BRCNPJField(Field):
new_2dv = DV_maker(new_2dv % 11)
value = value[:-1] + str(new_2dv)
if value[-2:] != orig_dv:
raise ValidationError(_("Invalid CNPJ number."))
raise ValidationError(self.error_messages['invalid'])
return orig_value

View File

@ -1,37 +1,43 @@
"""
Canada-specific Form helpers
"""
from django.newforms import ValidationError
from django.newforms.fields import Field, RegexField, Select, EMPTY_VALUES
from django.newforms.util import smart_unicode
"""
Canada-specific Form helpers
"""
from django.newforms import ValidationError
from django.newforms.fields import Field, RegexField, Select, EMPTY_VALUES
from django.newforms.util import smart_unicode
from django.utils.translation import gettext, ugettext
import re
import re
phone_digits_re = re.compile(r'^(?:1-?)?(\d{3})[-\.]?(\d{3})[-\.]?(\d{4})$')
sin_re = re.compile(r"^(\d{3})-(\d{3})-(\d{3})$")
class CAPostalCodeField(RegexField):
"""Canadian postal code field."""
def __init__(self, *args, **kwargs):
super(CAPostalCodeField, self).__init__(r'^[ABCEGHJKLMNPRSTVXYZ]\d[A-Z] \d[A-Z]\d$',
max_length=None, min_length=None,
error_message=gettext(u'Enter a postal code in the format XXX XXX.'),
*args, **kwargs)
class CAPhoneNumberField(Field):
"""Canadian phone number field."""
def clean(self, value):
"""Validate a phone number.
"""
super(CAPhoneNumberField, self).clean(value)
class CAPostalCodeField(RegexField):
"""Canadian postal code field."""
default_error_messages = {
'invalid': gettext(u'Enter a postal code in the format XXX XXX.'),
}
def __init__(self, *args, **kwargs):
super(CAPostalCodeField, self).__init__(r'^[ABCEGHJKLMNPRSTVXYZ]\d[A-Z] \d[A-Z]\d$',
max_length=None, min_length=None, *args, **kwargs)
class CAPhoneNumberField(Field):
"""Canadian phone number field."""
default_error_messages = {
'invalid': u'Phone numbers must be in XXX-XXX-XXXX format.',
}
def clean(self, value):
"""Validate a phone number.
"""
super(CAPhoneNumberField, self).clean(value)
if value in EMPTY_VALUES:
return u''
value = re.sub('(\(|\)|\s+)', '', smart_unicode(value))
m = phone_digits_re.search(value)
if m:
return u'%s-%s-%s' % (m.group(1), m.group(2), m.group(3))
raise ValidationError(u'Phone numbers must be in XXX-XXX-XXXX format.')
raise ValidationError(self.error_messages['invalid'])
class CAProvinceField(Field):
"""
@ -39,6 +45,10 @@ class CAProvinceField(Field):
It normalizes the input to the standard two-leter postal service
abbreviation for the given province.
"""
default_error_messages = {
'invalid': u'Enter a Canadian province or territory.',
}
def clean(self, value):
from ca_provinces import PROVINCES_NORMALIZED
super(CAProvinceField, self).clean(value)
@ -53,17 +63,17 @@ class CAProvinceField(Field):
return PROVINCES_NORMALIZED[value.strip().lower()].decode('ascii')
except KeyError:
pass
raise ValidationError(u'Enter a Canadian province or territory.')
class CAProvinceSelect(Select):
"""
A Select widget that uses a list of Canadian provinces and
territories as its choices.
"""
def __init__(self, attrs=None):
from ca_provinces import PROVINCE_CHOICES # relative import
raise ValidationError(self.error_messages['invalid'])
class CAProvinceSelect(Select):
"""
A Select widget that uses a list of Canadian provinces and
territories as its choices.
"""
def __init__(self, attrs=None):
from ca_provinces import PROVINCE_CHOICES # relative import
super(CAProvinceSelect, self).__init__(attrs, choices=PROVINCE_CHOICES)
class CASocialInsuranceNumberField(Field):
"""
A Canadian Social Insurance Number (SIN).
@ -74,24 +84,28 @@ class CASocialInsuranceNumberField(Field):
* Passes the check digit process "Luhn Algorithm"
See: http://en.wikipedia.org/wiki/Social_Insurance_Number
"""
default_error_messages = {
'invalid': ugettext('Enter a valid Canadian Social Insurance number in XXX-XXX-XXXX format.'),
}
def clean(self, value):
super(CASocialInsuranceNumberField, self).clean(value)
if value in EMPTY_VALUES:
return u''
msg = ugettext('Enter a valid Canadian Social Insurance number in XXX-XXX-XXXX format.')
match = re.match(sin_re, value)
if not match:
raise ValidationError(msg)
number = u'%s-%s-%s' % (match.group(1), match.group(2), match.group(3))
raise ValidationError(self.error_messages['invalid'])
number = u'%s-%s-%s' % (match.group(1), match.group(2), match.group(3))
check_number = u'%s%s%s' % (match.group(1), match.group(2), match.group(3))
if not self.luhn_checksum_is_valid(check_number):
raise ValidationError(msg)
raise ValidationError(self.error_messages['invalid'])
return number
def luhn_checksum_is_valid(self, number):
"""
Checks to make sure that the SIN passes a luhn mod-10 checksum
Checks to make sure that the SIN passes a luhn mod-10 checksum
See: http://en.wikipedia.org/wiki/Luhn_algorithm
"""
@ -109,4 +123,4 @@ class CASocialInsuranceNumberField(Field):
sum = sum + digit
return ( (sum % 10) == 0 )
return ( (sum % 10) == 0 )

View File

@ -12,11 +12,13 @@ id_re = re.compile(r"^(?P<idnumber>\w{8})(?P<pos9>(\d{1}|<))(?P<checksum>\d{1})$
phone_digits_re = re.compile(r'^0([1-9]{1})\d{8}$')
class CHZipCodeField(RegexField):
default_error_messages = {
'invalid': ugettext('Enter a zip code in the format XXXX.'),
}
def __init__(self, *args, **kwargs):
super(CHZipCodeField, self).__init__(r'^\d{4}$',
max_length=None, min_length=None,
error_message=ugettext('Enter a zip code in the format XXXX.'),
*args, **kwargs)
max_length=None, min_length=None, *args, **kwargs)
class CHPhoneNumberField(Field):
"""
@ -25,6 +27,10 @@ class CHPhoneNumberField(Field):
'0XX.XXX.XX.XX' and '0XXXXXXXXX' validate but are corrected to
'0XX XXX XX XX'.
"""
default_error_messages = {
'invalid': 'Phone numbers must be in 0XX XXX XX XX format.',
}
def clean(self, value):
super(CHPhoneNumberField, self).clean(value)
if value in EMPTY_VALUES:
@ -33,7 +39,7 @@ class CHPhoneNumberField(Field):
m = phone_digits_re.search(value)
if m:
return u'%s %s %s %s' % (value[0:3], value[3:6], value[6:8], value[8:10])
raise ValidationError('Phone numbers must be in 0XX XXX XX XX format.')
raise ValidationError(self.error_messages['invalid'])
class CHStateSelect(Select):
"""
@ -54,6 +60,10 @@ class CHIdentityCardNumberField(Field):
Algorithm is documented at http://adi.kousz.ch/artikel/IDCHE.htm
"""
default_error_messages = {
'invalid': ugettext('Enter a valid Swiss identity or passport card number in X1234567<0 or 1234567890 format.'),
}
def has_valid_checksum(self, number):
given_number, given_checksum = number[:-1], number[-1]
new_number = given_number
@ -87,23 +97,22 @@ class CHIdentityCardNumberField(Field):
def clean(self, value):
super(CHIdentityCardNumberField, self).clean(value)
error_msg = ugettext('Enter a valid Swiss identity or passport card number in X1234567<0 or 1234567890 format.')
if value in EMPTY_VALUES:
return u''
match = re.match(id_re, value)
if not match:
raise ValidationError(error_msg)
raise ValidationError(self.error_messages['invalid'])
idnumber, pos9, checksum = match.groupdict()['idnumber'], match.groupdict()['pos9'], match.groupdict()['checksum']
if idnumber == '00000000' or \
idnumber == 'A0000000':
raise ValidationError(error_msg)
raise ValidationError(self.error_messages['invalid'])
all_digits = "%s%s%s" % (idnumber, pos9, checksum)
if not self.has_valid_checksum(all_digits):
raise ValidationError(error_msg)
raise ValidationError(self.error_messages['invalid'])
return u'%s%s%s' % (idnumber, pos9, checksum)

View File

@ -25,16 +25,21 @@ class CLRutField(RegexField):
Samples for testing are available from
https://palena.sii.cl/cvc/dte/ee_empresas_emisoras.html
"""
default_error_messages = {
'invalid': ugettext('Enter a valid Chilean RUT.'),
'strict': ugettext('Enter a valid Chilean RUT. The format is XX.XXX.XXX-X.'),
'checksum': ugettext('The Chilean RUT is not valid.'),
}
def __init__(self, *args, **kwargs):
if 'strict' in kwargs:
del kwargs['strict']
super(CLRutField, self).__init__(r'^(\d{1,2}\.)?\d{3}\.\d{3}-[\dkK]$',
error_message=ugettext('Enter valid a Chilean RUT. The format is XX.XXX.XXX-X.'),
*args, **kwargs)
error_message=self.default_error_messages['strict'], *args, **kwargs)
else:
# In non-strict mode, accept RUTs that validate but do not exist in
# the real world.
super(CLRutField, self).__init__(r'^[\d\.]{1,11}-?[\dkK]$', error_message=ugettext('Enter valid a Chilean RUT'), *args, **kwargs)
super(CLRutField, self).__init__(r'^[\d\.]{1,11}-?[\dkK]$', *args, **kwargs)
def clean(self, value):
"""
@ -47,7 +52,7 @@ class CLRutField(RegexField):
if self._algorithm(rut) == verificador:
return self._format(rut, verificador)
else:
raise ValidationError(u'The Chilean RUT is not valid.')
raise ValidationError(self.error_messages['checksum'])
def _algorithm(self, rut):
"""

View File

@ -10,11 +10,12 @@ import re
id_re = re.compile(r"^(?P<residence>\d{10})(?P<origin>\w{1,3})[-\ ]?(?P<birthday>\d{7})[-\ ]?(?P<validity>\d{7})[-\ ]?(?P<checksum>\d{1})$")
class DEZipCodeField(RegexField):
default_error_messages = {
'invalid': ugettext('Enter a zip code in the format XXXXX.'),
}
def __init__(self, *args, **kwargs):
super(DEZipCodeField, self).__init__(r'^\d{5}$',
max_length=None, min_length=None,
error_message=ugettext('Enter a zip code in the format XXXXX.'),
*args, **kwargs)
max_length=None, min_length=None, *args, **kwargs)
class DEStateSelect(Select):
"""
@ -36,6 +37,10 @@ class DEIdentityCardNumberField(Field):
Algorithm is documented at http://de.wikipedia.org/wiki/Personalausweis
"""
default_error_messages = {
'invalid': ugettext('Enter a valid German identity card number in XXXXXXXXXXX-XXXXXXX-XXXXXXX-X format.'),
}
def has_valid_checksum(self, number):
given_number, given_checksum = number[:-1], number[-1]
calculated_checksum = 0
@ -57,23 +62,22 @@ class DEIdentityCardNumberField(Field):
def clean(self, value):
super(DEIdentityCardNumberField, self).clean(value)
error_msg = ugettext('Enter a valid German identity card number in XXXXXXXXXXX-XXXXXXX-XXXXXXX-X format.')
if value in EMPTY_VALUES:
return u''
match = re.match(id_re, value)
if not match:
raise ValidationError(error_msg)
raise ValidationError(self.error_messages['invalid'])
gd = match.groupdict()
residence, origin = gd['residence'], gd['origin']
birthday, validity, checksum = gd['birthday'], gd['validity'], gd['checksum']
if residence == '0000000000' or birthday == '0000000' or validity == '0000000':
raise ValidationError(error_msg)
raise ValidationError(self.error_messages['invalid'])
all_digits = u"%s%s%s%s" % (residence, birthday, validity, checksum)
if not self.has_valid_checksum(residence) or not self.has_valid_checksum(birthday) or \
not self.has_valid_checksum(validity) or not self.has_valid_checksum(all_digits):
raise ValidationError(error_msg)
raise ValidationError(self.error_messages['invalid'])
return u'%s%s-%s-%s-%s' % (residence, origin, birthday, validity, checksum)

View File

@ -15,12 +15,14 @@ class ESPostalCodeField(RegexField):
Spanish postal code is a five digits string, with two first digits
between 01 and 52, assigned to provinces code.
"""
default_error_messages = {
'invalid': _('Enter a valid postal code in the range and format 01XXX - 52XXX.'),
}
def __init__(self, *args, **kwargs):
super(ESPostalCodeField, self).__init__(
r'^(0[1-9]|[1-4][0-9]|5[0-2])\d{3}$',
max_length=None, min_length=None,
error_message=_('Enter a valid postal code in the range and format 01XXX - 52XXX.'),
*args, **kwargs)
max_length=None, min_length=None, *args, **kwargs)
class ESPhoneNumberField(RegexField):
"""
@ -33,11 +35,13 @@ class ESPhoneNumberField(RegexField):
TODO: accept and strip characters like dot, hyphen... in phone number
"""
default_error_messages = {
'invalid': _('Enter a valid phone number in one of the formats 6XXXXXXXX, 8XXXXXXXX or 9XXXXXXXX.'),
}
def __init__(self, *args, **kwargs):
super(ESPhoneNumberField, self).__init__(r'^(6|8|9)\d{8}$',
max_length=None, min_length=None,
error_message=_('Enter a valid phone number in one of the formats 6XXXXXXXX, 8XXXXXXXX or 9XXXXXXXX.'),
*args, **kwargs)
max_length=None, min_length=None, *args, **kwargs)
class ESIdentityCardNumberField(RegexField):
"""
@ -58,19 +62,23 @@ class ESIdentityCardNumberField(RegexField):
public, and different authors have different opinions on which ones allows
letters, so both validations are assumed true for all types.
"""
default_error_messages = {
'invalid': _('Please enter a valid NIF, NIE, or CIF.'),
'invalid_only_nif': _('Please enter a valid NIF or NIE.'),
'invalid_nif': _('Invalid checksum for NIF.'),
'invalid_nie': _('Invalid checksum for NIE.'),
'invalid_cif': _('Invalid checksum for CIF.'),
}
def __init__(self, only_nif=False, *args, **kwargs):
self.only_nif = only_nif
self.nif_control = 'TRWAGMYFPDXBNJZSQVHLCKE'
self.cif_control = 'JABCDEFGHI'
self.cif_types = 'ABCDEFGHKLMNPQS'
self.nie_types = 'XT'
if self.only_nif:
self.id_types = 'NIF or NIE'
else:
self.id_types = 'NIF, NIE, or CIF'
super(ESIdentityCardNumberField, self).__init__(r'^([%s]?)[ -]?(\d+)[ -]?([%s]?)$' % (self.cif_types + self.nie_types + self.cif_types.lower() + self.nie_types.lower(), self.nif_control + self.nif_control.lower()),
max_length=None, min_length=None,
error_message=_('Please enter a valid %s.' % self.id_types),
error_message=self.default_error_messages['invalid%s' % (self.only_nif and '_only_nif' or '')],
*args, **kwargs)
def clean(self, value):
@ -88,13 +96,13 @@ class ESIdentityCardNumberField(RegexField):
if letter2 == nif_get_checksum(number):
return value
else:
raise ValidationError, _('Invalid checksum for NIF.')
raise ValidationError, self.error_messages['invalid_nif']
elif letter1 in self.nie_types and letter2:
# NIE
if letter2 == nif_get_checksum(number):
return value
else:
raise ValidationError, _('Invalid checksum for NIE.')
raise ValidationError, self.error_messages['invalid_nie']
elif not self.only_nif and letter1 in self.cif_types and len(number) in [7, 8]:
# CIF
if not letter2:
@ -103,9 +111,9 @@ class ESIdentityCardNumberField(RegexField):
if letter2 in [checksum, self.cif_control[checksum]]:
return value
else:
raise ValidationError, _('Invalid checksum for CIF.')
raise ValidationError, self.error_messages['invalid_cif']
else:
raise ValidationError, _('Please enter a valid %s.' % self.id_types)
raise ValidationError, self.error_messages['invalid']
class ESCCCField(RegexField):
"""
@ -130,11 +138,14 @@ class ESCCCField(RegexField):
TODO: allow IBAN validation too
"""
default_error_messages = {
'invalid': _('Please enter a valid bank account number in format XXXX-XXXX-XX-XXXXXXXXXX.'),
'checksum': _('Invalid checksum for bank account number.'),
}
def __init__(self, *args, **kwargs):
super(ESCCCField, self).__init__(r'^\d{4}[ -]?\d{4}[ -]?\d{2}[ -]?\d{10}$',
max_length=None, min_length=None,
error_message=_('Please enter a valid bank account number in format XXXX-XXXX-XX-XXXXXXXXXX.'),
*args, **kwargs)
max_length=None, min_length=None, *args, **kwargs)
def clean(self, value):
super(ESCCCField, self).clean(value)
@ -147,7 +158,7 @@ class ESCCCField(RegexField):
if get_checksum('00' + entity + office) + get_checksum(account) == checksum:
return value
else:
raise ValidationError, _('Invalid checksum for bank account number.')
raise ValidationError, self.error_messages['checksum']
class ESRegionSelect(Select):
"""

View File

@ -8,11 +8,12 @@ from django.newforms.fields import Field, RegexField, Select, EMPTY_VALUES
from django.utils.translation import ugettext
class FIZipCodeField(RegexField):
default_error_messages = {
'invalid': ugettext('Enter a zip code in the format XXXXX.'),
}
def __init__(self, *args, **kwargs):
super(FIZipCodeField, self).__init__(r'^\d{5}$',
max_length=None, min_length=None,
error_message=ugettext('Enter a zip code in the format XXXXX.'),
*args, **kwargs)
max_length=None, min_length=None, *args, **kwargs)
class FIMunicipalitySelect(Select):
"""
@ -23,6 +24,10 @@ class FIMunicipalitySelect(Select):
super(FIMunicipalitySelect, self).__init__(attrs, choices=MUNICIPALITY_CHOICES)
class FISocialSecurityNumber(Field):
default_error_messages = {
'invalid': ugettext('Enter a valid Finnish social security number.'),
}
def clean(self, value):
super(FISocialSecurityNumber, self).clean(value)
if value in EMPTY_VALUES:
@ -37,9 +42,9 @@ class FISocialSecurityNumber(Field):
(?P<serial>(\d{3}))
(?P<checksum>[%s])$""" % checkmarks, value, re.VERBOSE | re.IGNORECASE)
if not result:
raise ValidationError(ugettext('Enter a valid Finnish social security number.'))
raise ValidationError(self.error_messages['invalid'])
gd = result.groupdict()
checksum = int(gd['date'] + gd['serial'])
if checkmarks[checksum % len(checkmarks)] == gd['checksum'].upper():
return u'%s' % value.upper()
raise ValidationError(ugettext('Enter a valid Finnish social security number.'))
raise ValidationError(self.error_messages['invalid'])

View File

@ -11,11 +11,13 @@ import re
phone_digits_re = re.compile(r'^0\d(\s|\.)?(\d{2}(\s|\.)?){3}\d{2}$')
class FRZipCodeField(RegexField):
default_error_messages = {
'invalid': ugettext('Enter a zip code in the format XXXXX.'),
}
def __init__(self, *args, **kwargs):
super(FRZipCodeField, self).__init__(r'^\d{5}$',
max_length=None, min_length=None,
error_message=ugettext('Enter a zip code in the format XXXXX.'),
*args, **kwargs)
max_length=None, min_length=None, *args, **kwargs)
class FRPhoneNumberField(Field):
"""
@ -24,6 +26,10 @@ class FRPhoneNumberField(Field):
'0X.XX.XX.XX.XX' and '0XXXXXXXXX' validate but are corrected to
'0X XX XX XX XX'.
"""
default_error_messages = {
'invalid': u'Phone numbers must be in 0X XX XX XX XX format.',
}
def clean(self, value):
super(FRPhoneNumberField, self).clean(value)
if value in EMPTY_VALUES:
@ -32,7 +38,7 @@ class FRPhoneNumberField(Field):
m = phone_digits_re.search(value)
if m:
return u'%s %s %s %s %s' % (value[0:2], value[2:4], value[4:6], value[6:8], value[8:10])
raise ValidationError(u'Phone numbers must be in 0X XX XX XX XX format.')
raise ValidationError(self.error_messages['invalid'])
class FRDepartmentSelect(Select):
"""

View File

@ -10,11 +10,13 @@ import re
class INZipCodeField(RegexField):
default_error_messages = {
'invalid': gettext(u'Enter a zip code in the format XXXXXXX.'),
}
def __init__(self, *args, **kwargs):
super(INZipCodeField, self).__init__(r'^\d{6}$',
max_length=None, min_length=None,
error_message=gettext(u'Enter a zip code in the format XXXXXXX.'),
*args, **kwargs)
max_length=None, min_length=None, *args, **kwargs)
class INStateField(Field):
"""
@ -22,6 +24,10 @@ class INStateField(Field):
abbreviation. It normalizes the input to the standard two-letter vehicle
registration abbreviation for the given state or union territory
"""
default_error_messages = {
'invalid': u'Enter a Indian state or territory.',
}
def clean(self, value):
from in_states import STATES_NORMALIZED
super(INStateField, self).clean(value)
@ -36,7 +42,7 @@ class INStateField(Field):
return smart_unicode(STATES_NORMALIZED[value.strip().lower()])
except KeyError:
pass
raise ValidationError(u'Enter a Indian state or territory.')
raise ValidationError(self.error_messages['invalid'])
class INStateSelect(Select):
"""

View File

@ -13,10 +13,14 @@ class ISIdNumberField(RegexField):
Icelandic identification number (kennitala). This is a number every citizen
of Iceland has.
"""
default_error_messages = {
'invalid': ugettext('Enter a valid Icelandic identification number. The format is XXXXXX-XXXX.'),
'checksum': ugettext(u'The Icelandic identification number is not valid.'),
}
def __init__(self, *args, **kwargs):
error_msg = ugettext('Enter a valid Icelandic identification number. The format is XXXXXX-XXXX.')
kwargs['min_length'],kwargs['max_length'] = 10,11
super(ISIdNumberField, self).__init__(r'^\d{6}(-| )?\d{4}$', error_message=error_msg, *args, **kwargs)
super(ISIdNumberField, self).__init__(r'^\d{6}(-| )?\d{4}$', *args, **kwargs)
def clean(self, value):
value = super(ISIdNumberField, self).clean(value)
@ -28,7 +32,7 @@ class ISIdNumberField(RegexField):
if self._validate(value):
return self._format(value)
else:
raise ValidationError(ugettext(u'The Icelandic identification number is not valid.'))
raise ValidationError(self.error_messages['checksum'])
def _canonify(self, value):
"""

View File

@ -10,11 +10,12 @@ from django.contrib.localflavor.it.util import ssn_check_digit, vat_number_check
import re
class ITZipCodeField(RegexField):
default_error_messages = {
'invalid': ugettext('Enter a valid zip code.'),
}
def __init__(self, *args, **kwargs):
super(ITZipCodeField, self).__init__(r'^\d{5}$',
max_length=None, min_length=None,
error_message=ugettext('Enter a valid zip code.'),
*args, **kwargs)
max_length=None, min_length=None, *args, **kwargs)
class ITRegionSelect(Select):
"""
@ -38,11 +39,13 @@ class ITSocialSecurityNumberField(RegexField):
For reference see http://www.agenziaentrate.it/ and search for
'Informazioni sulla codificazione delle persone fisiche'.
"""
err_msg = ugettext(u'Enter a valid Social Security number.')
default_error_messages = {
'invalid': ugettext(u'Enter a valid Social Security number.'),
}
def __init__(self, *args, **kwargs):
super(ITSocialSecurityNumberField, self).__init__(r'^\w{3}\s*\w{3}\s*\w{5}\s*\w{5}$',
max_length=None, min_length=None, error_message=self.err_msg,
*args, **kwargs)
max_length=None, min_length=None, *args, **kwargs)
def clean(self, value):
value = super(ITSocialSecurityNumberField, self).clean(value)
@ -52,26 +55,29 @@ class ITSocialSecurityNumberField(RegexField):
try:
check_digit = ssn_check_digit(value)
except ValueError:
raise ValidationError(self.err_msg)
raise ValidationError(self.error_messages['invalid'])
if not value[15] == check_digit:
raise ValidationError(self.err_msg)
raise ValidationError(self.error_messages['invalid'])
return value
class ITVatNumberField(Field):
"""
A form field that validates Italian VAT numbers (partita IVA).
"""
default_error_messages = {
'invalid': ugettext(u'Enter a valid VAT number.'),
}
def clean(self, value):
value = super(ITVatNumberField, self).clean(value)
if value == u'':
return value
err_msg = ugettext(u'Enter a valid VAT number.')
try:
vat_number = int(value)
except ValueError:
raise ValidationError(err_msg)
raise ValidationError(self.error_messages['invalid'])
vat_number = str(vat_number).zfill(11)
check_digit = vat_number_check_digit(vat_number[0:10])
if not vat_number[10] == check_digit:
raise ValidationError(err_msg)
raise ValidationError(self.error_messages['invalid'])
return smart_unicode(vat_number)

View File

@ -15,11 +15,13 @@ class JPPostalCodeField(RegexField):
Accepts 7 digits, with or without a hyphen.
"""
default_error_messages = {
'invalid': ugettext('Enter a postal code in the format XXXXXXX or XXX-XXXX.'),
}
def __init__(self, *args, **kwargs):
super(JPPostalCodeField, self).__init__(r'^\d{3}-\d{4}$|^\d{7}$',
max_length=None, min_length=None,
error_message=ugettext('Enter a postal code in the format XXXXXXX or XXX-XXXX.'),
*args, **kwargs)
max_length=None, min_length=None, *args, **kwargs)
def clean(self, value):
"""

View File

@ -17,24 +17,27 @@ class NLZipCodeField(Field):
"""
A Dutch postal code field.
"""
default_error_messages = {
'invalid': _('Enter a valid postal code'),
}
def clean(self, value):
super(NLZipCodeField, self).clean(value)
if value in EMPTY_VALUES:
return u''
msg = _('Enter a valid postal code')
value = value.strip().upper().replace(' ', '')
if not pc_re.search(value):
raise ValidationError(msg)
raise ValidationError(self.error_messages['invalid'])
if int(value[:4]) < 1000:
raise ValidationError(msg)
raise ValidationError(self.error_messages['invalid'])
return u'%s %s' % (value[:4], value[4:])
class NLProvinceSelect(Select):
"""
A Select widget that uses a list of provinces of the Netherlands as its
A Select widget that uses a list of provinces of the Netherlands as its
choices.
"""
def __init__(self, attrs=None):
@ -45,48 +48,53 @@ class NLPhoneNumberField(Field):
"""
A Dutch telephone number field.
"""
default_error_messages = {
'invalid': _('Enter a valid phone number'),
}
def clean(self, value):
super(NLPhoneNumberField, self).clean(value)
if value in EMPTY_VALUES:
return u''
msg = _('Enter a valid phone number')
phone_nr = re.sub('[\-\s\(\)]', '', smart_unicode(value))
if len(phone_nr) == 10 and numeric_re.search(phone_nr):
return value
if phone_nr[:3] == '+31' and len(phone_nr) == 12 and \
numeric_re.search(phone_nr[3:]):
return value
raise ValidationError(msg)
raise ValidationError(self.error_messages['invalid'])
class NLSoFiNumberField(Field):
"""
A Dutch social security number (SoFi/BSN) field.
http://nl.wikipedia.org/wiki/Sofinummer
"""
default_error_messages = {
'invalid': _('Enter a valid SoFi number'),
}
def clean(self, value):
super(NLSoFiNumberField, self).clean(value)
if value in EMPTY_VALUES:
return u''
msg = _('Enter a valid SoFi number')
if not sofi_re.search(value):
raise ValidationError(msg)
raise ValidationError(self.error_messages['invalid'])
if int(value) == 0:
raise ValidationError(msg)
raise ValidationError(self.error_messages['invalid'])
checksum = 0
for i in range(9, 1, -1):
checksum += int(value[9-i]) * i
checksum -= int(value[-1])
if checksum % 11 != 0:
raise ValidationError(msg)
raise ValidationError(self.error_messages['invalid'])
return value

View File

@ -8,11 +8,13 @@ from django.newforms.fields import Field, RegexField, Select, EMPTY_VALUES
from django.utils.translation import ugettext
class NOZipCodeField(RegexField):
default_error_messages = {
'invalid': ugettext('Enter a zip code in the format XXXX.'),
}
def __init__(self, *args, **kwargs):
super(NOZipCodeField, self).__init__(r'^\d{4}$',
max_length=None, min_length=None,
error_message=ugettext('Enter a zip code in the format XXXX.'),
*args, **kwargs)
max_length=None, min_length=None, *args, **kwargs)
class NOMunicipalitySelect(Select):
"""
@ -27,14 +29,17 @@ class NOSocialSecurityNumber(Field):
"""
Algorithm is documented at http://no.wikipedia.org/wiki/Personnummer
"""
default_error_messages = {
'invalid': ugettext(u'Enter a valid Norwegian social security number.'),
}
def clean(self, value):
super(NOSocialSecurityNumber, self).clean(value)
if value in EMPTY_VALUES:
return u''
msg = ugettext(u'Enter a valid Norwegian social security number.')
if not re.match(r'^\d{11}$', value):
raise ValidationError(msg)
raise ValidationError(self.error_messages['invalid'])
day = int(value[:2])
month = int(value[2:4])
@ -52,7 +57,7 @@ class NOSocialSecurityNumber(Field):
if 900 <= inum < 1000 and year2 > 39:
self.birthday = datetime.date(1900+year2, month, day)
except ValueError:
raise ValidationError(msg)
raise ValidationError(self.error_messages['invalid'])
sexnum = int(value[8])
if sexnum % 2 == 0:
@ -68,9 +73,9 @@ class NOSocialSecurityNumber(Field):
return sum([(a * b) for (a, b) in zip(aval, bval)])
if multiply_reduce(digits, weight_1) % 11 != 0:
raise ValidationError(msg)
raise ValidationError(self.error_messages['invalid'])
if multiply_reduce(digits, weight_2) % 11 != 0:
raise ValidationError(msg)
raise ValidationError(self.error_messages['invalid'])
return value

View File

@ -19,6 +19,11 @@ class PEDNIField(CharField):
"""
A field that validates `Documento Nacional de IdentidadŽ (DNI) numbers.
"""
default_error_messages = {
'invalid': ugettext("This field requires only numbers."),
'max_digits': ugettext("This field requires 8 digits."),
}
def __init__(self, *args, **kwargs):
super(PEDNIField, self).__init__(max_length=8, min_length=8, *args,
**kwargs)
@ -31,9 +36,9 @@ class PEDNIField(CharField):
if value in EMPTY_VALUES:
return u''
if not value.isdigit():
raise ValidationError(ugettext("This field requires only numbers."))
raise ValidationError(self.error_messages['invalid'])
if len(value) != 8:
raise ValidationError(ugettext("This field requires 8 digits."))
raise ValidationError(self.error_messages['max_digits'])
return value
@ -42,6 +47,11 @@ class PERUCField(RegexField):
This field validates a RUC (Registro Unico de Contribuyentes). A RUC is of
the form XXXXXXXXXXX.
"""
default_error_messages = {
'invalid': ugettext("This field requires only numbers."),
'max_digits': ugettext("This field requires 11 digits."),
}
def __init__(self, *args, **kwargs):
super(PERUCField, self).__init__(max_length=11, min_length=11, *args,
**kwargs)
@ -54,8 +64,8 @@ class PERUCField(RegexField):
if value in EMPTY_VALUES:
return u''
if not value.isdigit():
raise ValidationError(ugettext("This field requires only numbers."))
raise ValidationError(self.error_messages['invalid'])
if len(value) != 11:
raise ValidationError(ugettext("This field requires 11 digits."))
raise ValidationError(self.error_messages['max_digits'])
return value

View File

@ -35,16 +35,19 @@ class PLNationalIdentificationNumberField(RegexField):
The algorithm is documented at http://en.wikipedia.org/wiki/PESEL.
"""
default_error_messages = {
'invalid': _(u'National Identification Number consists of 11 digits.'),
'checksum': _(u'Wrong checksum for the National Identification Number.'),
}
def __init__(self, *args, **kwargs):
super(PLNationalIdentificationNumberField, self).__init__(r'^\d{11}$',
max_length=None, min_length=None, error_message=_(u'National Identification Number consists of 11 digits.'),
*args, **kwargs)
max_length=None, min_length=None, *args, **kwargs)
def clean(self,value):
super(PLNationalIdentificationNumberField, self).clean(value)
if not self.has_valid_checksum(value):
raise ValidationError(_(u'Wrong checksum for the National Identification Number.'))
raise ValidationError(self.error_messages['checksum'])
return u'%s' % value
def has_valid_checksum(self, number):
@ -65,17 +68,20 @@ class PLTaxNumberField(RegexField):
Checksum algorithm based on documentation at
http://wipos.p.lodz.pl/zylla/ut/nip-rego.html
"""
default_error_messages = {
'invalid': _(u'Enter a tax number field (NIP) in the format XXX-XXX-XX-XX or XX-XX-XXX-XXX.'),
'checksum': _(u'Wrong checksum for the Tax Number (NIP).'),
}
def __init__(self, *args, **kwargs):
super(PLTaxNumberField, self).__init__(r'^\d{3}-\d{3}-\d{2}-\d{2}$|^\d{2}-\d{2}-\d{3}-\d{3}$',
max_length=None, min_length=None,
error_message=_(u'Enter a tax number field (NIP) in the format XXX-XXX-XX-XX or XX-XX-XXX-XXX.'), *args, **kwargs)
max_length=None, min_length=None, *args, **kwargs)
def clean(self,value):
super(PLTaxNumberField, self).clean(value)
value = re.sub("[-]", "", value)
if not self.has_valid_checksum(value):
raise ValidationError(_(u'Wrong checksum for the Tax Number (NIP).'))
raise ValidationError(self.error_messages['checksum'])
return u'%s' % value
def has_valid_checksum(self, number):
@ -102,15 +108,19 @@ class PLNationalBusinessRegisterField(RegexField):
The checksum algorithm is documented at http://wipos.p.lodz.pl/zylla/ut/nip-rego.html
"""
default_error_messages = {
'invalid': _(u'National Business Register Number (REGON) consists of 7 or 9 digits.'),
'checksum': _(u'Wrong checksum for the National Business Register Number (REGON).'),
}
def __init__(self, *args, **kwargs):
super(PLNationalBusinessRegisterField, self).__init__(r'^\d{7,9}$',
max_length=None, min_length=None, error_message=_(u'National Business Register Number (REGON) consists of 7 or 9 digits.'),
*args, **kwargs)
max_length=None, min_length=None, *args, **kwargs)
def clean(self,value):
super(PLNationalBusinessRegisterField, self).clean(value)
if not self.has_valid_checksum(value):
raise ValidationError(_(u'Wrong checksum for the National Business Register Number (REGON).'))
raise ValidationError(self.error_messages['checksum'])
return u'%s' % value
def has_valid_checksum(self, number):
@ -142,9 +152,10 @@ class PLPostalCodeField(RegexField):
A form field that validates as Polish postal code.
Valid code is XX-XXX where X is digit.
"""
default_error_messages = {
'invalid': _(u'Enter a postal code in the format XX-XXX.'),
}
def __init__(self, *args, **kwargs):
super(PLPostalCodeField, self).__init__(r'^\d{2}-\d{3}$',
max_length=None, min_length=None,
error_message=_(u'Enter a postal code in the format XX-XXX.'),
*args, **kwargs)
max_length=None, min_length=None, *args, **kwargs)

View File

@ -26,11 +26,13 @@ class SKPostalCodeField(RegexField):
A form field that validates its input as Slovak postal code.
Valid form is XXXXX or XXX XX, where X represents integer.
"""
default_error_messages = {
'invalid': ugettext(u'Enter a postal code in the format XXXXX or XXX XX.'),
}
def __init__(self, *args, **kwargs):
super(SKPostalCodeField, self).__init__(r'^\d{5}$|^\d{3} \d{2}$',
max_length=None, min_length=None,
error_message=ugettext(u'Enter a postal code in the format XXXXX or XXX XX.'),
*args, **kwargs)
max_length=None, min_length=None, *args, **kwargs)
def clean(self, value):
"""

View File

@ -2,21 +2,39 @@
UK-specific Form helpers
"""
from django.newforms.fields import RegexField, Select
import re
from django.newforms.fields import CharField, Select
from django.newforms import ValidationError
from django.utils.translation import ugettext
class UKPostcodeField(RegexField):
class UKPostcodeField(CharField):
"""
A form field that validates its input is a UK postcode.
The regular expression used is sourced from the schema for British Standard
BS7666 address types: http://www.govtalk.gov.uk/gdsc/schemas/bs7666-v2-0.xsd
The value is uppercased and a space added in the correct place, if required.
"""
def __init__(self, *args, **kwargs):
super(UKPostcodeField, self).__init__(r'^(GIR 0AA|[A-PR-UWYZ]([0-9]{1,2}|([A-HIK-Y][0-9](|[0-9]|[ABEHMNPRVWXY]))|[0-9][A-HJKSTUW]) [0-9][ABD-HJLNP-UW-Z]{2})$',
max_length=None, min_length=None,
error_message=ugettext(u'Enter a postcode. A space is required between the two postcode parts.'),
*args, **kwargs)
default_error_messages = {
'invalid': ugettext(u'Enter a valid postcode.'),
}
outcode_pattern = '[A-PR-UWYZ]([0-9]{1,2}|([A-HIK-Y][0-9](|[0-9]|[ABEHMNPRVWXY]))|[0-9][A-HJKSTUW])'
incode_pattern = '[0-9][ABD-HJLNP-UW-Z]{2}'
postcode_regex = re.compile(r'^(GIR 0AA|%s %s)$' % (outcode_pattern, incode_pattern))
space_regex = re.compile(r' *(%s)$' % incode_pattern)
def clean(self, value):
value = super(UKPostcodeField, self).clean(value)
if value == u'':
return value
postcode = value.upper().strip()
# Put a single space before the incode (second part).
postcode = self.space_regex.sub(r' \1', postcode)
if not self.postcode_regex.search(postcode):
raise ValidationError(self.default_error_messages['invalid'])
return postcode
class UKCountySelect(Select):
"""

View File

@ -12,13 +12,19 @@ phone_digits_re = re.compile(r'^(?:1-?)?(\d{3})[-\.]?(\d{3})[-\.]?(\d{4})$')
ssn_re = re.compile(r"^(?P<area>\d{3})[-\ ]?(?P<group>\d{2})[-\ ]?(?P<serial>\d{4})$")
class USZipCodeField(RegexField):
default_error_messages = {
'invalid': ugettext('Enter a zip code in the format XXXXX or XXXXX-XXXX.'),
}
def __init__(self, *args, **kwargs):
super(USZipCodeField, self).__init__(r'^\d{5}(?:-\d{4})?$',
max_length=None, min_length=None,
error_message=ugettext('Enter a zip code in the format XXXXX or XXXXX-XXXX.'),
*args, **kwargs)
max_length=None, min_length=None, *args, **kwargs)
class USPhoneNumberField(Field):
default_error_messages = {
'invalid': u'Phone numbers must be in XXX-XXX-XXXX format.',
}
def clean(self, value):
super(USPhoneNumberField, self).clean(value)
if value in EMPTY_VALUES:
@ -27,7 +33,7 @@ class USPhoneNumberField(Field):
m = phone_digits_re.search(value)
if m:
return u'%s-%s-%s' % (m.group(1), m.group(2), m.group(3))
raise ValidationError(u'Phone numbers must be in XXX-XXX-XXXX format.')
raise ValidationError(self.error_messages['invalid'])
class USSocialSecurityNumberField(Field):
"""
@ -44,28 +50,31 @@ class USSocialSecurityNumberField(Field):
promotional use or distribution (e.g., the Woolworth's number or the
1962 promotional number).
"""
default_error_messages = {
'invalid': ugettext('Enter a valid U.S. Social Security number in XXX-XX-XXXX format.'),
}
def clean(self, value):
super(USSocialSecurityNumberField, self).clean(value)
if value in EMPTY_VALUES:
return u''
msg = ugettext('Enter a valid U.S. Social Security number in XXX-XX-XXXX format.')
match = re.match(ssn_re, value)
if not match:
raise ValidationError(msg)
raise ValidationError(self.error_messages['invalid'])
area, group, serial = match.groupdict()['area'], match.groupdict()['group'], match.groupdict()['serial']
# First pass: no blocks of all zeroes.
if area == '000' or \
group == '00' or \
serial == '0000':
raise ValidationError(msg)
raise ValidationError(self.error_messages['invalid'])
# Second pass: promotional and otherwise permanently invalid numbers.
if area == '666' or \
(area == '987' and group == '65' and 4320 <= int(serial) <= 4329) or \
value == '078-05-1120' or \
value == '219-09-9999':
raise ValidationError(msg)
raise ValidationError(self.error_messages['invalid'])
return u'%s-%s-%s' % (area, group, serial)
class USStateField(Field):
@ -74,6 +83,10 @@ class USStateField(Field):
It normalizes the input to the standard two-leter postal service
abbreviation for the given state.
"""
default_error_messages = {
'invalid': u'Enter a U.S. state or territory.',
}
def clean(self, value):
from us_states import STATES_NORMALIZED
super(USStateField, self).clean(value)
@ -88,7 +101,7 @@ class USStateField(Field):
return STATES_NORMALIZED[value.strip().lower()].decode('ascii')
except KeyError:
pass
raise ValidationError(u'Enter a U.S. state or territory.')
raise ValidationError(self.error_messages['invalid'])
class USStateSelect(Select):
"""

View File

@ -16,10 +16,9 @@ class ZAIDField(Field):
using the Luhn checksum, and uses a simlistic (read: not entirely accurate)
check for the birthdate
"""
def __init__(self, *args, **kwargs):
super(ZAIDField, self).__init__()
self.error_message = _(u'Enter a valid South African ID number')
default_error_messages = {
'invalid': _(u'Enter a valid South African ID number'),
}
def clean(self, value):
# strip spaces and dashes
@ -31,9 +30,9 @@ class ZAIDField(Field):
return u''
match = re.match(id_re, value)
if not match:
raise ValidationError(self.error_message)
raise ValidationError(self.error_messages['invalid'])
g = match.groupdict()
@ -43,15 +42,18 @@ class ZAIDField(Field):
# There is no way to guess the century of a ZA ID number
d = date(int(g['yy']) + 2000, int(g['mm']), int(g['dd']))
except ValueError:
raise ValidationError(self.error_message)
raise ValidationError(self.error_messages['invalid'])
if not luhn(value):
raise ValidationError(self.error_message)
raise ValidationError(self.error_messages['invalid'])
return value
class ZAPostCodeField(RegexField):
default_error_messages = {
'invalid': _(u'Enter a valid South African postal code'),
}
def __init__(self, *args, **kwargs):
super(ZAPostCodeField, self).__init__(r'^\d{4}$',
max_length=None, min_length=None,
error_message=_(u'Enter a valid South African postal code'))
max_length=None, min_length=None)

View File

@ -1,14 +1,23 @@
import os
import tempfile
from django.conf import settings
from django.contrib.sessions.backends.base import SessionBase
from django.core.exceptions import SuspiciousOperation
from django.core.exceptions import SuspiciousOperation, ImproperlyConfigured
class SessionStore(SessionBase):
"""
Implements a file based session store.
"""
def __init__(self, session_key=None):
self.storage_path = settings.SESSION_FILE_PATH
self.storage_path = getattr(settings, "SESSION_FILE_PATH", tempfile.gettempdir())
# Make sure the storage path is valid.
if not os.path.isdir(self.storage_path):
raise ImproperlyConfigured("The session storage path %r doesn't exist. "\
"Please set your SESSION_FILE_PATH setting "\
"to an existing directory in which Django "\
"can store session data." % self.storage_path)
self.file_prefix = settings.SESSION_COOKIE_NAME
super(SessionStore, self).__init__(session_key)

View File

@ -1,5 +1,6 @@
r"""
>>> from django.conf import settings
>>> from django.contrib.sessions.backends.db import SessionStore as DatabaseSession
>>> from django.contrib.sessions.backends.cache import SessionStore as CacheSession
>>> from django.contrib.sessions.backends.file import SessionStore as FileSession
@ -39,6 +40,13 @@ True
>>> file_session.exists(file_session.session_key)
False
# Make sure the file backend checks for a good storage dir
>>> settings.SESSION_FILE_PATH = "/if/this/directory/exists/you/have/a/weird/computer"
>>> FileSession()
Traceback (innermost last):
...
ImproperlyConfigured: The session storage path '/if/this/directory/exists/you/have/a/weird/computer' doesn't exist. Please set your SESSION_FILE_PATH setting to an existing directory in which Django can store session data.
>>> cache_session = CacheSession()
>>> cache_session.modified
False

View File

@ -1,12 +1,12 @@
"File-based cache backend"
import md5
import os, time
try:
import cPickle as pickle
except ImportError:
import pickle
from django.core.cache.backends.base import BaseCache
from django.utils.http import urlquote_plus
class CacheClass(BaseCache):
def __init__(self, dir, params):
@ -29,24 +29,10 @@ class CacheClass(BaseCache):
self._createdir()
def add(self, key, value, timeout=None):
fname = self._key_to_file(key)
if timeout is None:
timeout = self.default_timeout
try:
filelist = os.listdir(self._dir)
except (IOError, OSError):
self._createdir()
filelist = []
if len(filelist) > self._max_entries:
self._cull(filelist)
if os.path.basename(fname) not in filelist:
try:
f = open(fname, 'wb')
now = time.time()
pickle.dump(now + timeout, f, 2)
pickle.dump(value, f, 2)
except (IOError, OSError):
pass
if self.has_key(key):
return None
self.set(key, value, timeout)
def get(self, key, default=None):
fname = self._key_to_file(key)
@ -56,7 +42,7 @@ class CacheClass(BaseCache):
now = time.time()
if exp < now:
f.close()
os.remove(fname)
self._delete(fname)
else:
return pickle.load(f)
except (IOError, OSError, EOFError, pickle.PickleError):
@ -65,40 +51,74 @@ class CacheClass(BaseCache):
def set(self, key, value, timeout=None):
fname = self._key_to_file(key)
dirname = os.path.dirname(fname)
if timeout is None:
timeout = self.default_timeout
self._cull()
try:
filelist = os.listdir(self._dir)
except (IOError, OSError):
self._createdir()
filelist = []
if len(filelist) > self._max_entries:
self._cull(filelist)
try:
if not os.path.exists(dirname):
os.makedirs(dirname)
f = open(fname, 'wb')
now = time.time()
pickle.dump(now + timeout, f, 2)
pickle.dump(value, f, 2)
pickle.dump(now + timeout, f, pickle.HIGHEST_PROTOCOL)
pickle.dump(value, f, pickle.HIGHEST_PROTOCOL)
except (IOError, OSError):
pass
def delete(self, key):
try:
os.remove(self._key_to_file(key))
self._delete(self._key_to_file(key))
except (IOError, OSError):
pass
def _delete(self, fname):
os.remove(fname)
try:
# Remove the 2 subdirs if they're empty
dirname = os.path.dirname(fname)
os.rmdir(dirname)
os.rmdir(os.path.dirname(dirname))
except (IOError, OSError):
pass
def has_key(self, key):
return os.path.exists(self._key_to_file(key))
fname = self._key_to_file(key)
try:
f = open(fname, 'rb')
exp = pickle.load(f)
now = time.time()
if exp < now:
f.close()
self._delete(fname)
return False
else:
return True
except (IOError, OSError, EOFError, pickle.PickleError):
return False
def _cull(self, filelist):
def _cull(self):
if int(self._num_entries) < self._max_entries:
return
try:
filelist = os.listdir(self._dir)
except (IOError, OSError):
return
if self._cull_frequency == 0:
doomed = filelist
else:
doomed = [k for (i, k) in enumerate(filelist) if i % self._cull_frequency == 0]
for fname in doomed:
doomed = [os.path.join(self._dir, k) for (i, k) in enumerate(filelist) if i % self._cull_frequency == 0]
for topdir in doomed:
try:
os.remove(os.path.join(self._dir, fname))
for root, _, files in os.walk(topdir):
for f in files:
self._delete(os.path.join(root, f))
except (IOError, OSError):
pass
@ -109,4 +129,22 @@ class CacheClass(BaseCache):
raise EnvironmentError, "Cache directory '%s' does not exist and could not be created'" % self._dir
def _key_to_file(self, key):
return os.path.join(self._dir, urlquote_plus(key))
"""
Convert the filename into an md5 string. We'll turn the first couple
bits of the path into directory prefixes to be nice to filesystems
that have problems with large numbers of files in a directory.
Thus, a cache key of "foo" gets turnned into a file named
``{cache-dir}ac/bd/18db4cc2f85cedef654fccc4a4d8``.
"""
path = md5.new(key.encode('utf-8')).hexdigest()
path = os.path.join(path[:2], path[2:4], path[4:])
return os.path.join(self._dir, path)
def _get_num_entries(self):
count = 0
for _,_,files in os.walk(self._dir):
count += len(files)
return count
_num_entries = property(_get_num_entries)

View File

@ -29,51 +29,38 @@ class CacheClass(BaseCache):
self._lock = RWLock()
def _add(self, key, value, timeout=None):
if len(self._cache) >= self._max_entries:
self._cull()
if timeout is None:
timeout = self.default_timeout
if key not in self._cache.keys():
self._cache[key] = value
self._expire_info[key] = time.time() + timeout
def add(self, key, value, timeout=None):
self._lock.writer_enters()
# Python 2.3 and 2.4 don't allow combined try-except-finally blocks.
try:
try:
self._add(key, pickle.dumps(value), timeout)
except pickle.PickleError:
pass
exp = self._expire_info.get(key)
if exp is None or exp <= time.time():
try:
self._set(key, pickle.dumps(value), timeout)
except pickle.PickleError:
pass
finally:
self._lock.writer_leaves()
def get(self, key, default=None):
should_delete = False
self._lock.reader_enters()
try:
now = time.time()
exp = self._expire_info.get(key)
if exp is None:
return default
elif exp < now:
should_delete = True
else:
elif exp > time.time():
try:
return pickle.loads(self._cache[key])
except pickle.PickleError:
return default
finally:
self._lock.reader_leaves()
if should_delete:
self._lock.writer_enters()
try:
del self._cache[key]
del self._expire_info[key]
return default
finally:
self._lock.writer_leaves()
self._lock.writer_enters()
try:
del self._cache[key]
del self._expire_info[key]
return default
finally:
self._lock.writer_leaves()
def _set(self, key, value, timeout=None):
if len(self._cache) >= self._max_entries:
@ -95,7 +82,23 @@ class CacheClass(BaseCache):
self._lock.writer_leaves()
def has_key(self, key):
return key in self._cache
self._lock.reader_enters()
try:
exp = self._expire_info.get(key)
if exp is None:
return False
elif exp > time.time():
return True
finally:
self._lock.reader_leaves()
self._lock.writer_enters()
try:
del self._cache[key]
del self._expire_info[key]
return False
finally:
self._lock.writer_leaves()
def _cull(self):
if self._cull_frequency == 0:

View File

@ -10,7 +10,7 @@ from django.core.management.base import BaseCommand, CommandError, handle_defaul
get_version = django.get_version
# A cache of loaded commands, so that call_command
# doesn't have to reload every time it is called
# doesn't have to reload every time it's called.
_commands = None
def find_commands(management_dir):
@ -29,8 +29,8 @@ def find_commands(management_dir):
def find_management_module(app_name):
"""
Determines the path to the management module for the application named,
without acutally importing the application or the management module.
Determines the path to the management module for the given app_name,
without actually importing the application or the management module.
Raises ImportError if the management module cannot be found for any reason.
"""
@ -46,19 +46,19 @@ def find_management_module(app_name):
def load_command_class(app_name, name):
"""
Given a command name and an application name, returns the Command
class instance. All errors raised by the importation process
class instance. All errors raised by the import process
(ImportError, AttributeError) are allowed to propagate.
"""
return getattr(__import__('%s.management.commands.%s' % (app_name, name),
{}, {}, ['Command']), 'Command')()
def get_commands():
def get_commands(load_user_commands=True, project_directory=None):
"""
Returns a dictionary of commands against the application in which
those commands can be found. This works by looking for a
management.commands package in django.core, and in each installed
application -- if a commands package exists, all commands in that
package are registered.
Returns a dictionary mapping command names to their callback applications.
This works by looking for a management.commands package in django.core, and
in each installed application -- if a commands package exists, all commands
in that package are registered.
Core commands are always included. If a settings module has been
specified, user-defined commands will also be included, the
@ -73,34 +73,22 @@ def get_commands():
startapp command), the instantiated module can be placed in the
dictionary in place of the application name.
The dictionary is cached on the first call, and reused on subsequent
The dictionary is cached on the first call and reused on subsequent
calls.
"""
global _commands
if _commands is None:
_commands = dict([(name, 'django.core')
for name in find_commands(__path__[0])])
# Get commands from all installed apps.
try:
from django.conf import settings
apps = settings.INSTALLED_APPS
except (AttributeError, ImportError):
apps = []
_commands = dict([(name, 'django.core') for name in find_commands(__path__[0])])
for app_name in apps:
try:
path = find_management_module(app_name)
_commands.update(dict([(name, app_name)
for name in find_commands(path)]))
except ImportError:
pass # No management module - ignore this app
# Try to determine the project directory
try:
if load_user_commands:
# Get commands from all installed apps.
from django.conf import settings
project_directory = setup_environ(__import__(settings.SETTINGS_MODULE))
except (AttributeError, ImportError):
project_directory = None
for app_name in settings.INSTALLED_APPS:
try:
path = find_management_module(app_name)
_commands.update(dict([(name, app_name) for name in find_commands(path)]))
except ImportError:
pass # No management module -- ignore this app.
if project_directory:
# Remove the "startproject" command from self.commands, because
@ -157,18 +145,18 @@ class ManagementUtility(object):
def __init__(self, argv=None):
self.argv = argv or sys.argv[:]
self.prog_name = os.path.basename(self.argv[0])
self.project_directory = None
self.user_commands = False
def main_help_text(self):
"""
Returns the script's main help text, as a string.
"""
usage = ['%s <subcommand> [options] [args]' % self.prog_name]
usage.append('Django command line tool,'
' version %s' % django.get_version())
usage.append("Type '%s help <subcommand>' for help on a specific"
" subcommand." % self.prog_name)
usage.append('Django command line tool, version %s' % django.get_version())
usage.append("Type '%s help <subcommand>' for help on a specific subcommand." % self.prog_name)
usage.append('Available subcommands:')
commands = get_commands().keys()
commands = get_commands(self.user_commands, self.project_directory).keys()
commands.sort()
for cmd in commands:
usage.append(' %s' % cmd)
@ -178,18 +166,18 @@ class ManagementUtility(object):
"""
Tries to fetch the given subcommand, printing a message with the
appropriate command called from the command line (usually
django-admin.py or manage.py) if it can't be found.
"django-admin.py" or "manage.py") if it can't be found.
"""
try:
app_name = get_commands()[subcommand]
app_name = get_commands(self.user_commands, self.project_directory)[subcommand]
if isinstance(app_name, BaseCommand):
# If the command is already loaded, use it directly.
klass = app_name
else:
klass = load_command_class(app_name, subcommand)
except KeyError:
sys.stderr.write("Unknown command: %r\nType '%s help' for"
" usage.\n" % (subcommand, self.prog_name))
sys.stderr.write("Unknown command: %r\nType '%s help' for usage.\n" % \
(subcommand, self.prog_name))
sys.exit(1)
return klass
@ -201,8 +189,7 @@ class ManagementUtility(object):
# Preprocess options to extract --settings and --pythonpath.
# These options could affect the commands that are available, so they
# must be processed early.
parser = LaxOptionParser(version=get_version(),
option_list=BaseCommand.option_list)
parser = LaxOptionParser(version=get_version(), option_list=BaseCommand.option_list)
try:
options, args = parser.parse_args(self.argv)
handle_default_options(options)
@ -242,6 +229,8 @@ class ProjectManagementUtility(ManagementUtility):
"""
def __init__(self, argv, project_directory):
super(ProjectManagementUtility, self).__init__(argv)
self.project_directory = project_directory
self.user_commands = True
def setup_environ(settings_mod):
"""
@ -263,8 +252,7 @@ def setup_environ(settings_mod):
sys.path.pop()
# Set DJANGO_SETTINGS_MODULE appropriately.
os.environ['DJANGO_SETTINGS_MODULE'] = '%s.%s' % (project_name,
settings_name)
os.environ['DJANGO_SETTINGS_MODULE'] = '%s.%s' % (project_name, settings_name)
return project_directory
def execute_from_command_line(argv=None):

View File

@ -27,6 +27,8 @@ class BaseCommand(object):
help='The Python path to a settings module, e.g. "myproject.settings.main". If this isn\'t provided, the DJANGO_SETTINGS_MODULE environment variable will be used.'),
make_option('--pythonpath',
help='A directory to add to the Python path, e.g. "/home/djangoprojects/myproject".'),
make_option('--traceback', action='store_true',
help='Print traceback on exception'),
)
help = ''
args = ''

View File

@ -1,11 +1,12 @@
from django.core.management.base import BaseCommand, CommandError
from django.core import serializers
from optparse import make_option
class Command(BaseCommand):
option_list = BaseCommand.option_list + (
make_option('--format', default='json', dest='format',
help='Specifies the output serialization format for fixtures'),
help='Specifies the output serialization format for fixtures.'),
make_option('--indent', default=None, dest='indent', type='int',
help='Specifies the indent level to use when pretty-printing output'),
)
@ -14,10 +15,10 @@ class Command(BaseCommand):
def handle(self, *app_labels, **options):
from django.db.models import get_app, get_apps, get_models
from django.core import serializers
format = options.get('format', 'json')
indent = options.get('indent', None)
show_traceback = options.get('traceback', False)
if len(app_labels) == 0:
app_list = get_apps()
@ -26,6 +27,9 @@ class Command(BaseCommand):
# Check that the serialization format exists; this is a shortcut to
# avoid collating all the objects and _then_ failing.
if format not in serializers.get_public_serializer_formats():
raise CommandError("Unknown serialization format: %s" % format)
try:
serializers.get_serializer(format)
except KeyError:
@ -34,8 +38,10 @@ class Command(BaseCommand):
objects = []
for app in app_list:
for model in get_models(app):
objects.extend(model.objects.all())
objects.extend(model._default_manager.all())
try:
return serializers.serialize(format, objects, indent=indent)
except Exception, e:
if show_traceback:
raise
raise CommandError("Unable to serialize database: %s" % e)

View File

@ -27,6 +27,7 @@ class Command(BaseCommand):
self.style = no_style()
verbosity = int(options.get('verbosity', 1))
show_traceback = options.get('traceback', False)
# Keep a count of the installed objects and fixtures
count = [0, 0]
@ -50,15 +51,15 @@ class Command(BaseCommand):
parts = fixture_label.split('.')
if len(parts) == 1:
fixture_name = fixture_label
formats = serializers.get_serializer_formats()
formats = serializers.get_public_serializer_formats()
else:
fixture_name, format = '.'.join(parts[:-1]), parts[-1]
if format in serializers.get_serializer_formats():
if format in serializers.get_public_serializer_formats():
formats = [format]
else:
formats = []
if verbosity > 0:
if verbosity > 2:
if formats:
print "Loading '%s' fixtures..." % fixture_name
else:
@ -98,15 +99,17 @@ class Command(BaseCommand):
label_found = True
except Exception, e:
fixture.close()
transaction.rollback()
transaction.leave_transaction_management()
if show_traceback:
raise
sys.stderr.write(
self.style.ERROR("Problem installing fixture '%s': %s\n" %
(full_path, str(e))))
transaction.rollback()
transaction.leave_transaction_management()
return
fixture.close()
except:
if verbosity > 1:
if verbosity > 2:
print "No %s fixture '%s' in %s." % \
(format, fixture_name, humanize(fixture_dir))
@ -122,7 +125,7 @@ class Command(BaseCommand):
transaction.leave_transaction_management()
if count[0] == 0:
if verbosity > 0:
if verbosity > 2:
print "No fixtures found."
else:
if verbosity > 0:

View File

@ -116,6 +116,7 @@ def sql_delete(app, style):
"Returns a list of the DROP TABLE SQL statements for the given app."
from django.db import connection, models, get_introspection_module
from django.db.backends.util import truncate_name
from django.contrib.contenttypes import generic
introspection = get_introspection_module()
# This should work even if a connection isn't available
@ -179,6 +180,8 @@ def sql_delete(app, style):
for model in app_models:
opts = model._meta
for f in opts.many_to_many:
if isinstance(f.rel, generic.GenericRel):
continue
if cursor and table_name_converter(f.m2m_db_table()) in table_names:
output.append("%s %s;" % (style.SQL_KEYWORD('DROP TABLE'),
style.SQL_TABLE(qn(f.m2m_db_table()))))

View File

@ -53,6 +53,11 @@ def get_serializer_formats():
_load_serializers()
return _serializers.keys()
def get_public_serializer_formats():
if not _serializers:
_load_serializers()
return [k for k, v in _serializers.iteritems() if not v.Serializer.internal_use_only]
def get_deserializer(format):
if not _serializers:
_load_serializers()

View File

@ -22,6 +22,10 @@ class Serializer(object):
Abstract serializer base class.
"""
# Indicates if the implemented serializer is only available for
# internal Django use.
internal_use_only = False
def serialize(self, queryset, **options):
"""
Serialize a queryset.

View File

@ -20,6 +20,8 @@ class Serializer(PythonSerializer):
"""
Convert a queryset to JSON.
"""
internal_use_only = False
def end_serialization(self):
self.options.pop('stream', None)
self.options.pop('fields', None)

View File

@ -13,7 +13,9 @@ class Serializer(base.Serializer):
"""
Serializes a QuerySet to basic Python objects.
"""
internal_use_only = True
def start_serialization(self):
self._current = None
self.objects = []

View File

@ -5,6 +5,7 @@ Requires PyYaml (http://pyyaml.org/), but that's checked for in __init__.
"""
import datetime
from django.db import models
from django.core.serializers.python import Serializer as PythonSerializer
from django.core.serializers.python import Deserializer as PythonDeserializer
try:
@ -17,10 +18,25 @@ class Serializer(PythonSerializer):
"""
Convert a queryset to YAML.
"""
internal_use_only = False
def handle_field(self, obj, field):
# A nasty special case: base YAML doesn't support serialization of time
# types (as opposed to dates or datetimes, which it does support). Since
# we want to use the "safe" serializer for better interoperability, we
# need to do something with those pesky times. Converting 'em to strings
# isn't perfect, but it's better than a "!!python/time" type which would
# halt deserialization under any other language.
if isinstance(field, models.TimeField) and getattr(obj, field.name) is not None:
self._current[field.name] = str(getattr(obj, field.name))
else:
super(Serializer, self).handle_field(obj, field)
def end_serialization(self):
self.options.pop('stream', None)
self.options.pop('fields', None)
yaml.dump(self.objects, self.stream, **self.options)
yaml.safe_dump(self.objects, self.stream, **self.options)
def getvalue(self):
return self.stream.getvalue()

View File

@ -398,8 +398,20 @@ class ServerHandler(object):
self.bytes_sent += len(data)
# XXX check Content-Length and truncate if too many bytes written?
self._write(data)
self._flush()
# If data is too large, socket will choke, so write chunks no larger
# than 32MB at a time.
length = len(data)
if length > 33554432:
offset = 0
while offset < length:
chunk_size = min(33554432, length)
self._write(data[offset:offset+chunk_size])
self._flush()
offset += chunk_size
else:
self._write(data)
self._flush()
def sendfile(self):
"""Platform-specific file transmission

View File

@ -34,8 +34,8 @@ except ImportError, e:
raise # If there's some other error, this must be an error in Django itself.
def _import_database_module(import_path='', module_name=''):
"""Lazyily import a database module when requested."""
return __import__('%s%s.%s' % (_import_path, settings.DATABASE_ENGINE, module_name), {}, {}, [''])
"""Lazily import a database module when requested."""
return __import__('%s%s.%s' % (import_path, settings.DATABASE_ENGINE, module_name), {}, {}, [''])
# We don't want to import the introspect/creation modules unless
# someone asks for 'em, so lazily load them on demmand.

View File

@ -455,6 +455,23 @@ class FormatStylePlaceholderCursor(Database.Cursor):
else:
return tuple([smart_str(p, self.charset, True) for p in params])
def _guess_input_sizes(self, params_list):
# Mark any string parameter greater than 4000 characters as an NCLOB.
if isinstance(params_list[0], dict):
sizes = {}
iterators = [params.iteritems() for params in params_list]
else:
sizes = [None] * len(params_list[0])
iterators = [enumerate(params) for params in params_list]
for iterator in iterators:
for key, value in iterator:
if isinstance(value, basestring) and len(value) > 4000:
sizes[key] = Database.NCLOB
if isinstance(sizes, dict):
self.setinputsizes(**sizes)
else:
self.setinputsizes(*sizes)
def execute(self, query, params=None):
if params is None:
params = []
@ -468,6 +485,7 @@ class FormatStylePlaceholderCursor(Database.Cursor):
if query.endswith(';') or query.endswith('/'):
query = query[:-1]
query = smart_str(query, self.charset) % tuple(args)
self._guess_input_sizes([params])
return Database.Cursor.execute(self, query, params)
def executemany(self, query, params=None):
@ -484,6 +502,7 @@ class FormatStylePlaceholderCursor(Database.Cursor):
query = query[:-1]
query = smart_str(query, self.charset) % tuple(args)
new_param_list = [self._format_params(i) for i in params]
self._guess_input_sizes(new_param_list)
return Database.Cursor.executemany(self, query, new_param_list)
def fetchone(self):

View File

@ -708,7 +708,7 @@ class EmailField(CharField):
class FileField(Field):
def __init__(self, verbose_name=None, name=None, upload_to='', **kwargs):
self.upload_to = upload_to
kwargs['max_length'] = kwargs.get('max_length', 100)
kwargs['max_length'] = kwargs.get('max_length', 100)
Field.__init__(self, verbose_name, name, **kwargs)
def get_db_prep_save(self, value):
@ -905,9 +905,13 @@ class NullBooleanField(Field):
return [oldforms.NullBooleanField]
def formfield(self, **kwargs):
defaults = {'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text}
defaults = {
'form_class': forms.NullBooleanField,
'required': not self.blank,
'label': capfirst(self.verbose_name),
'help_text': self.help_text}
defaults.update(kwargs)
return forms.NullBooleanField(**defaults)
return super(NullBooleanField, self).formfield(**defaults)
class PhoneNumberField(IntegerField):
def get_manipulator_field_objs(self):
@ -925,11 +929,11 @@ class PhoneNumberField(IntegerField):
class PositiveIntegerField(IntegerField):
def get_manipulator_field_objs(self):
return [oldforms.PositiveIntegerField]
def formfield(self, **kwargs):
defaults = {'min_value': 0}
defaults.update(kwargs)
return super(PositiveIntegerField, self).formfield(**defaults)
return super(PositiveIntegerField, self).formfield(**defaults)
class PositiveSmallIntegerField(IntegerField):
def get_manipulator_field_objs(self):
@ -938,7 +942,7 @@ class PositiveSmallIntegerField(IntegerField):
def formfield(self, **kwargs):
defaults = {'min_value': 0}
defaults.update(kwargs)
return super(PositiveSmallIntegerField, self).formfield(**defaults)
return super(PositiveSmallIntegerField, self).formfield(**defaults)
class SlugField(CharField):
def __init__(self, *args, **kwargs):

View File

@ -277,7 +277,20 @@ class HttpResponse(object):
for key, value in self._headers.values()]) \
+ '\n\n' + self.content
def _convert_to_ascii(self, *values):
"Convert all values to ascii strings"
for value in values:
if isinstance(value, unicode):
try:
yield value.encode('us-ascii')
except UnicodeError, e:
e.reason += ', HTTP response headers must be in US-ASCII format'
raise
else:
yield str(value)
def __setitem__(self, header, value):
header, value = self._convert_to_ascii(header, value)
self._headers[header.lower()] = (header, value)
def __delitem__(self, header):
@ -331,7 +344,7 @@ class HttpResponse(object):
chunk = self._iterator.next()
if isinstance(chunk, unicode):
chunk = chunk.encode(self._charset)
return chunk
return str(chunk)
def close(self):
if hasattr(self._container, 'close'):

View File

@ -533,8 +533,8 @@ class BooleanField(Field):
"""Returns a Python boolean object."""
super(BooleanField, self).clean(value)
# Explicitly check for the string 'False', which is what a hidden field
# will submit for False (since bool("True") == True we don't need to
# handle that explicitly).
# will submit for False. Because bool("True") == True, we don't need to
# handle that explicitly.
if value == 'False':
return False
return bool(value)

View File

@ -86,9 +86,8 @@ def form_for_model(model, form=BaseForm, fields=None,
determining the formfield for a given database field. It's a callable that
takes a database Field instance and returns a form Field instance.
"""
warn("form_for_model is deprecated, use ModelForm instead.",
PendingDeprecationWarning,
stacklevel=3)
warn("form_for_model is deprecated. Use ModelForm instead.",
PendingDeprecationWarning, stacklevel=3)
opts = model._meta
field_list = []
for f in opts.fields + opts.many_to_many:
@ -116,9 +115,8 @@ def form_for_instance(instance, form=BaseForm, fields=None,
takes a database Field instance, plus **kwargs, and returns a form Field
instance with the given kwargs (i.e. 'initial').
"""
warn("form_for_instance is deprecated, use ModelForm instead.",
PendingDeprecationWarning,
stacklevel=3)
warn("form_for_instance is deprecated. Use ModelForm instead.",
PendingDeprecationWarning, stacklevel=3)
model = instance.__class__
opts = model._meta
field_list = []
@ -151,10 +149,10 @@ def model_to_dict(instance, fields=None, exclude=None):
"""
Returns a dict containing the data in ``instance`` suitable for passing as
a Form's ``initial`` keyword argument.
``fields`` is an optional list of field names. If provided, only the named
fields will be included in the returned dict.
``exclude`` is an optional list of field names. If provided, the named
fields will be excluded from the returned dict, even if they are listed in
the ``fields`` argument.
@ -189,7 +187,7 @@ def fields_for_model(model, fields=None, exclude=None, formfield_callback=lambda
``fields`` is an optional list of field names. If provided, only the named
fields will be included in the returned fields.
``exclude`` is an optional list of field names. If provided, the named
fields will be excluded from the returned fields, even if they are listed
in the ``fields`` argument.
@ -216,9 +214,8 @@ class ModelFormOptions(object):
self.exclude = getattr(options, 'exclude', None)
class ModelFormMetaclass(type):
def __new__(cls, name, bases, attrs):
# TODO: no way to specify formfield_callback yet, do we need one, or
# should it be a special case for the admin?
def __new__(cls, name, bases, attrs,
formfield_callback=lambda f: f.formfield()):
fields = [(field_name, attrs.pop(field_name)) for field_name, obj in attrs.items() if isinstance(obj, Field)]
fields.sort(lambda x, y: cmp(x[1].creation_counter, y[1].creation_counter))
@ -247,15 +244,16 @@ class ModelFormMetaclass(type):
# If a model is defined, extract form fields from it and add them to base_fields
if attrs['_meta'].model is not None:
# Don't allow a subclass to define a Meta model if a parent class has.
# Technically the right fields would be generated, but the save
# method will not deal with more than one model.
# Don't allow a subclass to define a different Meta model than a
# parent class has. Technically the right fields would be generated,
# but the save method will not deal with more than one model.
for base in bases:
base_opts = getattr(base, '_meta', None)
base_model = getattr(base_opts, 'model', None)
if base_model is not None:
raise ImproperlyConfigured('%s defines more than one model.' % name)
model_fields = fields_for_model(opts.model, opts.fields, opts.exclude)
if base_model and base_model is not opts.model:
raise ImproperlyConfigured('%s defines a different model than its parent.' % name)
model_fields = fields_for_model(opts.model, opts.fields,
opts.exclude, formfield_callback)
# fields declared in base classes override fields from the model
model_fields.update(declared_fields)
attrs['base_fields'] = model_fields
@ -264,11 +262,16 @@ class ModelFormMetaclass(type):
return type.__new__(cls, name, bases, attrs)
class BaseModelForm(BaseForm):
def __init__(self, instance, data=None, files=None, auto_id='id_%s', prefix=None,
initial=None, error_class=ErrorList, label_suffix=':'):
self.instance = instance
def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
initial=None, error_class=ErrorList, label_suffix=':', instance=None):
opts = self._meta
object_data = model_to_dict(instance, opts.fields, opts.exclude)
if instance is None:
# if we didn't get an instance, instantiate a new one
self.instance = opts.model()
object_data = {}
else:
self.instance = instance
object_data = model_to_dict(instance, opts.fields, opts.exclude)
# if initial was provided, it should override the values from instance
if initial is not None:
object_data.update(initial)

View File

@ -43,7 +43,11 @@ def stringfilter(func):
def addslashes(value):
"""Adds slashes - useful for passing strings to JavaScript, for example."""
"""
Adds slashes before quotes. Useful for escaping strings in CSV, for
example. Less useful for escaping JavaScript; use the ``escapejs``
filter instead.
"""
return value.replace('\\', '\\\\').replace('"', '\\"').replace("'", "\\'")
addslashes.is_safe = True
addslashes = stringfilter(addslashes)
@ -54,6 +58,25 @@ def capfirst(value):
capfirst.is_safe=True
capfirst = stringfilter(capfirst)
_js_escapes = (
('\\', '\\\\'),
('"', '\\"'),
("'", "\\'"),
('\n', '\\n'),
('\r', '\\r'),
('\b', '\\b'),
('\f', '\\f'),
('\t', '\\t'),
('\v', '\\v'),
('</', '<\\/'),
)
def escapejs(value):
"""Backslash-escapes characters for use in JavaScript strings."""
for bad, good in _js_escapes:
value = value.replace(bad, good)
return value
escapejs = stringfilter(escapejs)
def fix_ampersands(value):
"""Replaces ampersands with ``&amp;`` entities."""
from django.utils.html import fix_ampersands
@ -231,7 +254,7 @@ urlize.is_safe=True
urlize.needs_autoescape = True
urlize = stringfilter(urlize)
def urlizetrunc(value, limit):
def urlizetrunc(value, limit, autoescape=None):
"""
Converts URLs into clickable links, truncating URLs to the given character
limit, and adding 'rel=nofollow' attribute to discourage spamming.
@ -239,8 +262,10 @@ def urlizetrunc(value, limit):
Argument: Length to truncate URLs to.
"""
from django.utils.html import urlize
return mark_safe(urlize(value, trim_url_limit=int(limit), nofollow=True))
return mark_safe(urlize(value, trim_url_limit=int(limit), nofollow=True,
autoescape=autoescape))
urlizetrunc.is_safe = True
urlizetrunc.needs_autoescape = True
urlizetrunc = stringfilter(urlizetrunc)
def wordcount(value):
@ -766,6 +791,7 @@ register.filter(dictsort)
register.filter(dictsortreversed)
register.filter(divisibleby)
register.filter(escape)
register.filter(escapejs)
register.filter(filesizeformat)
register.filter(first)
register.filter(fix_ampersands)

View File

@ -814,7 +814,7 @@ def ssi(parser, token):
Outputs the contents of a given file into the page.
Like a simple "include" tag, the ``ssi`` tag includes the contents
of another file -- which must be specified using an absolute page --
of another file -- which must be specified using an absolute path --
in the current page::
{% ssi /home/html/ljworld.com/includes/right_generic.html %}

View File

@ -1,4 +1,4 @@
import sys, time
import sys, time, os
from django.conf import settings
from django.db import connection, get_creation_module
from django.core import mail
@ -106,9 +106,32 @@ def create_test_db(verbosity=1, autoclobber=False):
if verbosity >= 1:
print "Creating test database..."
# If we're using SQLite, it's more convenient to test against an
# in-memory database.
# in-memory database. Using the TEST_DATABASE_NAME setting you can still choose
# to run on a physical database.
if settings.DATABASE_ENGINE == "sqlite3":
TEST_DATABASE_NAME = ":memory:"
if settings.TEST_DATABASE_NAME and settings.TEST_DATABASE_NAME != ":memory:":
TEST_DATABASE_NAME = settings.TEST_DATABASE_NAME
# Erase the old test database
if verbosity >= 1:
print "Destroying old test database..."
if os.access(TEST_DATABASE_NAME, os.F_OK):
if not autoclobber:
confirm = raw_input("Type 'yes' if you would like to try deleting the test database '%s', or 'no' to cancel: " % TEST_DATABASE_NAME)
if autoclobber or confirm == 'yes':
try:
if verbosity >= 1:
print "Destroying old test database..."
os.remove(TEST_DATABASE_NAME)
except Exception, e:
sys.stderr.write("Got an error deleting the old test database: %s\n" % e)
sys.exit(2)
else:
print "Tests cancelled."
sys.exit(1)
if verbosity >= 1:
print "Creating test database..."
else:
TEST_DATABASE_NAME = ":memory:"
else:
suffix = {
'postgresql': get_postgresql_create_suffix,
@ -171,17 +194,20 @@ def destroy_test_db(old_database_name, verbosity=1):
creation_module.destroy_test_db(settings, connection, old_database_name, verbosity)
return
# Unless we're using SQLite, remove the test database to clean up after
# ourselves. Connect to the previous database (not the test database)
# to do so, because it's not allowed to delete a database while being
# connected to it.
if verbosity >= 1:
print "Destroying test database..."
connection.close()
TEST_DATABASE_NAME = settings.DATABASE_NAME
settings.DATABASE_NAME = old_database_name
if settings.DATABASE_ENGINE != "sqlite3":
if settings.DATABASE_ENGINE == "sqlite3":
if TEST_DATABASE_NAME and TEST_DATABASE_NAME != ":memory:":
# Remove the SQLite database file
os.remove(TEST_DATABASE_NAME)
else:
# Remove the test database to clean up after
# ourselves. Connect to the previous database (not the test database)
# to do so, because it's not allowed to delete a database while being
# connected to it.
cursor = connection.cursor()
_set_autocommit(connection)
time.sleep(1) # To avoid "database is being accessed by other users" errors.

View File

@ -1,4 +1,4 @@
"HTML utilities suitable for global use."
"""HTML utilities suitable for global use."""
import re
import string
@ -8,11 +8,11 @@ from django.utils.encoding import force_unicode
from django.utils.functional import allow_lazy
from django.utils.http import urlquote
# Configuration for urlize() function
# Configuration for urlize() function.
LEADING_PUNCTUATION = ['(', '<', '&lt;']
TRAILING_PUNCTUATION = ['.', ',', ')', '>', '\n', '&gt;']
# list of possible strings used for bullets in bulleted lists
# List of possible strings used for bullets in bulleted lists.
DOTS = ['&middot;', '*', '\xe2\x80\xa2', '&#149;', '&bull;', '&#8226;']
unencoded_ampersands_re = re.compile(r'&(?!(\w+|#\d+);)')
@ -28,7 +28,7 @@ trailing_empty_content_re = re.compile(r'(?:<p>(?:&nbsp;|\s|<br \/>)*?</p>\s*)+\
del x # Temporary variable
def escape(html):
"Return the given HTML with ampersands, quotes and carets encoded."
"""Returns the given HTML with ampersands, quotes and carets encoded."""
return mark_safe(force_unicode(html).replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;').replace('"', '&quot;').replace("'", '&#39;'))
escape = allow_lazy(escape, unicode)
@ -42,7 +42,7 @@ def conditional_escape(html):
return escape(html)
def linebreaks(value, autoescape=False):
"Converts newlines into <p> and <br />s"
"""Converts newlines into <p> and <br />s."""
value = re.sub(r'\r\n|\r|\n', '\n', force_unicode(value)) # normalize newlines
paras = re.split('\n{2,}', value)
if autoescape:
@ -50,31 +50,31 @@ def linebreaks(value, autoescape=False):
else:
paras = [u'<p>%s</p>' % p.strip().replace('\n', '<br />') for p in paras]
return u'\n\n'.join(paras)
linebreaks = allow_lazy(linebreaks, unicode)
linebreaks = allow_lazy(linebreaks, unicode)
def strip_tags(value):
"Return the given HTML with all tags stripped."
"""Returns the given HTML with all tags stripped."""
return re.sub(r'<[^>]*?>', '', force_unicode(value))
strip_tags = allow_lazy(strip_tags)
def strip_spaces_between_tags(value):
"Return the given HTML with spaces between tags removed."
"""Returns the given HTML with spaces between tags removed."""
return re.sub(r'>\s+<', '><', force_unicode(value))
strip_spaces_between_tags = allow_lazy(strip_spaces_between_tags, unicode)
def strip_entities(value):
"Return the given HTML with all entities (&something;) stripped."
"""Returns the given HTML with all entities (&something;) stripped."""
return re.sub(r'&(?:\w+|#\d+);', '', force_unicode(value))
strip_entities = allow_lazy(strip_entities, unicode)
def fix_ampersands(value):
"Return the given HTML with all unencoded ampersands encoded correctly."
"""Returns the given HTML with all unencoded ampersands encoded correctly."""
return unencoded_ampersands_re.sub('&amp;', force_unicode(value))
fix_ampersands = allow_lazy(fix_ampersands, unicode)
def urlize(text, trim_url_limit=None, nofollow=False, autoescape=False):
"""
Convert any URLs in text into clickable links.
Converts any URLs in text into clickable links.
Works on http://, https://, and www. links. Links can have trailing
punctuation (periods, commas, close-parens) and leading punctuation

View File

@ -1,6 +1,6 @@
"""
Utilities for providing backwards compatibility for the maxlength argument,
which has been replaced by max_length, see ticket #2101.
which has been replaced by max_length. See ticket #2101.
"""
from warnings import warn
@ -15,17 +15,15 @@ def legacy_maxlength(max_length, maxlength):
"""
Consolidates max_length and maxlength, providing backwards compatibilty
for the legacy "maxlength" argument.
If one of max_length or maxlength is given, then that value is returned.
If both are given, a TypeError is raised.
If maxlength is used at all, a deprecation warning is issued.
If both are given, a TypeError is raised. If maxlength is used at all, a
deprecation warning is issued.
"""
if maxlength is not None:
warn("maxlength is deprecated, use max_length instead.",
DeprecationWarning,
stacklevel=3)
warn("maxlength is deprecated. Use max_length instead.", DeprecationWarning, stacklevel=3)
if max_length is not None:
raise TypeError("field can not take both the max_length"
" argument and the legacy maxlength argument.")
raise TypeError("Field cannot take both the max_length argument and the legacy maxlength argument.")
max_length = maxlength
return max_length
@ -33,7 +31,8 @@ def remove_maxlength(func):
"""
A decorator to be used on a class's __init__ that provides backwards
compatibilty for the legacy "maxlength" keyword argument, i.e.
name = models.CharField(maxlength=20)
name = models.CharField(maxlength=20)
It does this by changing the passed "maxlength" keyword argument
(if it exists) into a "max_length" keyword argument.
"""
@ -58,7 +57,6 @@ class LegacyMaxlength(type):
Metaclass for providing backwards compatibility support for the
"maxlength" keyword argument.
"""
def __init__(cls, name, bases, attrs):
super(LegacyMaxlength, cls).__init__(name, bases, attrs)
# Decorate the class's __init__ to remove any maxlength keyword.

View File

@ -1,9 +1,12 @@
import os
import re
import sys
from django.conf import settings
from django.template import Template, Context, TemplateDoesNotExist
from django.utils.html import escape
from django.http import HttpResponseServerError, HttpResponseNotFound
from django.utils.encoding import smart_unicode
import os, re, sys
HIDDEN_SETTINGS = re.compile('SECRET|PASSWORD|PROFANITIES_LIST')
@ -142,9 +145,10 @@ def technical_500_response(request, exc_type, exc_value, tb):
'request': request,
'request_protocol': request.is_secure() and "https" or "http",
'settings': get_safe_settings(),
'sys_executable' : sys.executable,
'sys_version_info' : '%d.%d.%d' % sys.version_info[0:3],
'django_version_info' : get_version(),
'sys_executable': sys.executable,
'sys_version_info': '%d.%d.%d' % sys.version_info[0:3],
'django_version_info': get_version(),
'sys_path' : sys.path,
'template_info': template_info,
'template_does_not_exist': template_does_not_exist,
'loader_debug_info': loader_debug_info,
@ -230,8 +234,8 @@ TECHNICAL_500_TEMPLATE = """
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta name="robots" content="NONE,NOARCHIVE" />
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="robots" content="NONE,NOARCHIVE">
<title>{{ exception_type }} at {{ request.path|escape }}</title>
<style type="text/css">
html * { padding:0; margin:0; }
@ -368,6 +372,10 @@ TECHNICAL_500_TEMPLATE = """
<th>Python Version:</th>
<td>{{ sys_version_info }}</td>
</tr>
<tr>
<th>Python Path:</th>
<td>{{ sys_path }}</td>
</tr>
</table>
</div>
{% if unicode_hint %}
@ -460,10 +468,10 @@ TECHNICAL_500_TEMPLATE = """
{% endautoescape %}
<form action="http://dpaste.com/" name="pasteform" id="pasteform" method="post">
<div id="pastebinTraceback" class="pastebin">
<input type="hidden" name="language" value="PythonConsole" />
<input type="hidden" name="title" value="{{ exception_type|escape }} at {{ request.path|escape }}" />
<input type="hidden" name="source" value="Django Dpaste Agent" />
<input type="hidden" name="poster" value="Django" />
<input type="hidden" name="language" value="PythonConsole">
<input type="hidden" name="title" value="{{ exception_type|escape }} at {{ request.path|escape }}">
<input type="hidden" name="source" value="Django Dpaste Agent">
<input type="hidden" name="poster" value="Django">
<textarea name="content" id="traceback_area" cols="140" rows="25">
Environment:
@ -471,10 +479,10 @@ Request Method: {{ request.META.REQUEST_METHOD }}
Request URL: {{ request_protocol }}://{{ request.META.HTTP_HOST }}{{ request.path|escape }}
Django Version: {{ django_version_info }}
Python Version: {{ sys_version_info }}
Installed Applications:
{{ settings.INSTALLED_APPS|pprint }}
Installed Middleware:
{{ settings.MIDDLEWARE_CLASSES|pprint }}
Installed Applications:
{{ settings.INSTALLED_APPS|pprint }}
Installed Middleware:
{{ settings.MIDDLEWARE_CLASSES|pprint }}
{% if template_does_not_exist %}Template Loader Error:
{% if loader_debug_info %}Django tried loading these templates, in this order:
@ -498,9 +506,9 @@ Traceback:
Exception Type: {{ exception_type|escape }} at {{ request.path|escape }}
Exception Value: {{ exception_value|escape }}
</textarea>
<br/><br/>
<br><br>
<input type="submit" value="Share this traceback on public Web site">
</div>
<input type="submit" value="Send to DPaste">
</form>
</div>
@ -627,9 +635,9 @@ TECHNICAL_404_TEMPLATE = """
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>Page not found at {{ request.path|escape }}</title>
<meta name="robots" content="NONE,NOARCHIVE" />
<meta name="robots" content="NONE,NOARCHIVE">
<style type="text/css">
html * { padding:0; margin:0; }
body * { padding:10px 20px; }

View File

@ -59,10 +59,11 @@ def serve(request, path, document_root=None, show_indexes=False):
if not was_modified_since(request.META.get('HTTP_IF_MODIFIED_SINCE'),
statobj[stat.ST_MTIME], statobj[stat.ST_SIZE]):
return HttpResponseNotModified()
mimetype = mimetypes.guess_type(fullpath)[0]
mimetype = mimetypes.guess_type(fullpath)[0] or 'application/octet-stream'
contents = open(fullpath, 'rb').read()
response = HttpResponse(contents, mimetype=mimetype)
response["Last-Modified"] = http_date(statobj[stat.ST_MTIME])
response["Content-Length"] = len(contents)
return response
DEFAULT_DIRECTORY_INDEX_TEMPLATE = """

View File

@ -47,7 +47,11 @@ contenttypes
============
A light framework for hooking into "types" of content, where each installed
Django model is a separate content type. This is not yet documented.
Django model is a separate content type.
See the `contenttypes documentation`_.
.. _contenttypes documentation: ../contenttypes/
csrf
====
@ -177,9 +181,13 @@ localflavor
===========
A collection of various Django snippets that are useful only for a particular
country or culture. For example, ``django.contrib.localflavor.usa.forms``
country or culture. For example, ``django.contrib.localflavor.us.forms``
contains a ``USZipCodeField`` that you can use to validate U.S. zip codes.
See the `localflavor documentation`_.
.. _localflavor documentation: ../localflavor/
markup
======
@ -252,12 +260,12 @@ See the `syndication documentation`_.
webdesign
=========
Helpers and utilties targeted primarily at web designers rather than
web developers.
Helpers and utilties targeted primarily at Web *designers* rather than
Web *developers*.
See the `web design helpers documentation`_.
See the `Web design helpers documentation`_.
.. _web design helpers documentation: ../webdesign/
.. _Web design helpers documentation: ../webdesign/
Other add-ons
=============

View File

@ -247,8 +247,8 @@ Anonymous users
the ``django.contrib.auth.models.User`` interface, with these differences:
* ``id`` is always ``None``.
* ``is_staff`` and ``is_superuser`` are always False.
* ``is_active`` is always True.
* ``is_staff`` and ``is_superuser`` are always ``False``.
* ``is_active`` is always ``False``.
* ``groups`` and ``user_permissions`` are always empty.
* ``is_anonymous()`` returns ``True`` instead of ``False``.
* ``is_authenticated()`` returns ``False`` instead of ``True``.
@ -382,7 +382,7 @@ This example shows how you might use both ``authenticate()`` and ``login()``::
.. admonition:: Calling ``authenticate()`` first
When you're manually logging a user in, you *must* call
``authenticate()`` before you call ``login()``; ``authenticate()``
``authenticate()`` before you call ``login()``. ``authenticate()``
sets an attribute on the ``User`` noting which authentication
backend successfully authenticated that user (see the `backends
documentation`_ for details), and this information is needed later

View File

@ -254,9 +254,10 @@ Second, note the five triage stages:
3. Once a ticket is ruled to be approved for fixing, it's moved into the
"Accepted" stage. This stage is where all the real work gets done.
4. A ticket might be moved to the "Someday/Maybe" state if it's an
enhancement request we are willing to consider if a good patch is
written. Such tickets are not high priority.
4. In some cases, a ticket might get moved to the "Someday/Maybe" state.
This means the ticket is an enhancement request that we might consider
adding to the framework if an excellent patch is submitted. These
tickets are not a high priority.
5. If a ticket has an associated patch (see below), a triager will review
the patch. If the patch is complete, it'll be marked as "ready for

View File

@ -44,8 +44,8 @@ Our class looks something like this::
# ... (other possibly useful methods omitted) ...
This is just an ordinary Python class, with nothing Django-specific about it.
We'd like to be able to things like this in our models (we assume the ``hand``
attribute on the model is an instance of ``Hand``)::
We'd like to be able to do things like this in our models (we assume the
``hand`` attribute on the model is an instance of ``Hand``)::
example = MyModel.objects.get(pk=1)
print example.hand.north
@ -382,6 +382,10 @@ database, so we need to be able to process strings and ``Hand`` instances in
Notice that we always return a ``Hand`` instance from this method. That's the
Python object type we want to store in the model's attribute.
**Remember:** If your custom field needs the ``to_python()`` method to be
called when it is created, you should be using `The SubfieldBase metaclass`_
mentioned earlier. Otherwise ``to_python()`` won't be called automatically.
``get_db_prep_save(self, value)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -258,11 +258,10 @@ many-to-many table would be stored in the ``indexes`` tablespace. The ``data``
field would also generate an index, but no tablespace for it is specified, so
it would be stored in the model tablespace ``tables`` by default.
The settings.py file supports two additional options to specify
default values for the db_tablespace options. This is useful for
setting a tablespace for the Django internal apps and other
contributed applications. These options are ``DEFAULT_TABLESPACE``
and ``DEFAULT_INDEX_TABLESPACE``.
**New in the Django development version:** Use the ``DEFAULT_TABLESPACE`` and
``DEFAULT_INDEX_TABLESPACE`` settings to specify default values for the
db_tablespace options. These are useful for setting a tablespace for the
built-in Django apps and other applications whose code you cannot control.
Django does not create the tablespaces for you. Please refer to `Oracle's
documentation`_ for details on creating and managing tablespaces.

View File

@ -132,6 +132,13 @@ If no application name is provided, all installed applications will be dumped.
The output of ``dumpdata`` can be used as input for ``loaddata``.
Note that ``dumpdata`` uses the default manager on the model for selecting the
records to dump. If you're using a `custom manager`_ as the default manager
and it filters some of the available records, not all of the objects will be
dumped.
.. _custom manager: ../model-api/#custom-managers
--format
~~~~~~~~

View File

@ -1,6 +1,13 @@
Generating forms for models
===========================
.. admonition:: Note
The APIs described in this document have been deprecated. If you're
developing new code, use `ModelForms`_ instead.
.. _ModelForms: ../modelforms/
If you're building a database-driven app, chances are you'll have forms that
map closely to Django models. For instance, you might have a ``BlogComment``
model, and you want to create a form that lets people submit comments. In this

View File

@ -76,14 +76,12 @@ automatically create database tables for your models, you'll need to
ensure that Django has permission to create and alter tables in the
database you're using; if you plan to manually create the tables, you
can simply grant Django ``SELECT``, ``INSERT``, ``UPDATE`` and
``DELETE`` permissions. On some databases, Django will need to have
``ALTER TABLE`` privileges during ``syncdb`` (in order to create
foreign key constraints properly on databases which do not allow them
to be deferred), but will not issue ``ALTER TABLE`` statements on a
table once ``syncdb`` has finished setting it up.
``DELETE`` permissions. On some databases, Django will need
``ALTER TABLE`` privileges during ``syncdb`` but won't issue
``ALTER TABLE`` statements on a table once ``syncdb`` has created it.
If you will be using Django's `testing framework`_ with data fixtures,
Django will need permission to create a temporary test database.
If you're using Django's `testing framework`_ to test database queries,
Django will need permission to create a test database.
.. _PostgreSQL: http://www.postgresql.org/
.. _MySQL: http://www.mysql.com/

View File

@ -2,16 +2,22 @@
The "local flavor" add-ons
==========================
Django comes with assorted pieces of code that are useful only for a particular
country or culture. These pieces of code are organized as a set of
Following its "batteries included" philosophy, Django comes with assorted
pieces of code that are useful for particular countries or cultures. These are
called the "local flavor" add-ons and live in the ``django.contrib.localflavor``
package.
Inside that package, country- or culture-specific code is organized into
subpackages, named using `ISO 3166 country codes`_.
.. _ISO 3166 country codes: http://www.iso.org/iso/country_codes/iso_3166_code_lists/english_country_names_and_code_elements.htm
Most of the ``localflavor`` add-ons are localized form components deriving from
the newforms_ framework. To use one of these localized components, just import
the relevant subpackage. For example, a form with a field for French telephone
numbers is created like so::
the newforms_ framework -- for example, a ``USStateField`` that knows how to
validate U.S. state abbreviations, and a ``FISocialSecurityNumber`` that knows
how to validate Finnish social security numbers.
To use one of these localized components, just import the relevant subpackage.
For example, here's how you can create a form with a field representing a
French telephone number::
from django import newforms as forms
from django.contrib.localflavor import fr
@ -19,32 +25,48 @@ numbers is created like so::
class MyForm(forms.Form):
my_french_phone_no = fr.forms.FRPhoneNumberField()
Supported countries
===================
Countries currently supported by ``localflavor`` are:
* Argentina_
* Australia_
* Brazil_
* Canada_
* Chile_
* Finland_
* France_
* Germany_
* Holland_
* Iceland_
* India_
* Italy_
* Japan_
* Mexico_
* Norway_
* Peru_
* Poland_
* Slovakia_
* `South Africa`_
* Spain_
* Switzerland_
* `United Kingdom`_
* `United States of America`_
* Argentina_
* Australia_
* Brazil_
* Canada_
* Chile_
* Finland_
* France_
* Germany_
* Holland_
* Iceland_
* India_
* Italy_
* Japan_
* Mexico_
* Norway_
* Peru_
* Poland_
* Slovakia_
* `South Africa`_
* Spain_
* Switzerland_
* `United Kingdom`_
* `United States of America`_
The ``localflavor`` package also includes a ``generic`` subpackage, containing
useful code that is not specific to one particular country or culture.
Currently, it defines date and datetime input fields based on those from
newforms_, but with non-US default formats. Here's an example of how to use
them::
from django import newforms as forms
from django.contrib.localflavor import generic
class MyForm(forms.Form):
my_date_field = generic.forms.DateField()
.. _ISO 3166 country codes: http://www.iso.org/iso/country_codes/iso_3166_code_lists/english_country_names_and_code_elements.htm
.. _Argentina: `Argentina (django.contrib.localflavor.ar)`_
.. _Australia: `Australia (django.contrib.localflavor.au)`_
.. _Brazil: `Brazil (django.contrib.localflavor.br)`_
@ -68,29 +90,15 @@ Countries currently supported by ``localflavor`` are:
.. _Switzerland: `Switzerland (django.contrib.localflavor.ch)`_
.. _United Kingdom: `United Kingdom (django.contrib.localflavor.uk)`_
.. _United States of America: `United States of America (django.contrib.localflavor.us)`_
The ``localflavor`` add-on also includes the ``generic`` subpackage, containing
useful code that is not specific to one particular country or culture.
Currently, it defines date and date & time input fields based on those from
newforms_, but with non-US default formats. Here's an example of how to use
them::
from django import newforms as forms
from django.contrib.localflavor import generic
class MyForm(forms.Form):
my_date_field = generic.forms.DateField()
.. _newforms: ../newforms/
Adding flavors
==============
.. admonition:: Adding a Flavor
We'd love to add more of these to Django, so please create a ticket for
anything that you've found useful. Please use unicode objects
(``u'mystring'``) for strings, rather than setting the encoding in the file
(see any of the existing flavors for examples).
We'd love to add more of these to Django, so please `create a ticket`_ with
any code you'd like to contribute. One thing we ask is that you please use
Unicode objects (``u'mystring'``) for strings, rather than setting the encoding
in the file. See any of the existing flavors for examples.
Argentina (``django.contrib.localflavor.ar``)
=============================================
@ -108,7 +116,6 @@ ARProvinceSelect
A ``Select`` widget that uses a list of Argentina's provinces as its choices.
Australia (``django.contrib.localflavor.au``)
=============================================
@ -129,7 +136,6 @@ AUStateSelect
A ``Select`` widget that uses a list of Australian states/territories as its
choices.
Brazil (``django.contrib.localflavor.br``)
==========================================
@ -151,7 +157,6 @@ BRStateSelect
A ``Select`` widget that uses a list of Brazilian states/territories as its
choices.
Canada (``django.contrib.localflavor.ca``)
==========================================
@ -187,7 +192,6 @@ CAProvinceSelect
A ``Select`` widget that uses a list of Canadian provinces and territories as
its choices.
Chile (``django.contrib.localflavor.cl``)
=========================================
@ -203,7 +207,6 @@ CLRegionSelect
A ``Select`` widget that uses a list of Chilean regions (Regiones) as its
choices.
Finland (``django.contrib.localflavor.fi``)
===========================================
@ -215,7 +218,7 @@ A form field that validates input as a Finnish social security number.
FIZipCodeField
--------------
A form field that validates input as a Finnish zip code. Valid codes
A form field that validates input as a Finnish zip code. Valid codes
consist of five digits.
FIMunicipalitySelect
@ -224,7 +227,6 @@ FIMunicipalitySelect
A ``Select`` widget that uses a list of Finnish municipalities as its
choices.
France (``django.contrib.localflavor.fr``)
==========================================
@ -232,13 +234,13 @@ FRPhoneNumberField
------------------
A form field that validates input as a French local phone number. The
correct format is 0X XX XX XX XX. 0X.XX.XX.XX.XX and 0XXXXXXXXX validate
correct format is 0X XX XX XX XX. 0X.XX.XX.XX.XX and 0XXXXXXXXX validate
but are corrected to 0X XX XX XX XX.
FRZipCodeField
--------------
A form field that validates input as a French zip code. Valid codes
A form field that validates input as a French zip code. Valid codes
consist of five digits.
FRDepartmentSelect
@ -246,7 +248,6 @@ FRDepartmentSelect
A ``Select`` widget that uses a list of French departments as its choices.
Germany (``django.contrib.localflavor.de``)
===========================================
@ -254,7 +255,7 @@ DEIdentityCardNumberField
-------------------------
A form field that validates input as a German identity card number
(Personalausweis_). Valid numbers have the format
(Personalausweis_). Valid numbers have the format
XXXXXXXXXXX-XXXXXXX-XXXXXXX-X, with no group consisting entirely of zeroes.
.. _Personalausweis: http://de.wikipedia.org/wiki/Personalausweis
@ -262,7 +263,7 @@ XXXXXXXXXXX-XXXXXXX-XXXXXXX-X, with no group consisting entirely of zeroes.
DEZipCodeField
--------------
A form field that validates input as a German zip code. Valid codes
A form field that validates input as a German zip code. Valid codes
consist of five digits.
DEStateSelect
@ -270,7 +271,6 @@ DEStateSelect
A ``Select`` widget that uses a list of German states as its choices.
Holland (``django.contrib.localflavor.nl``)
===========================================
@ -296,7 +296,6 @@ NLProvinceSelect
A ``Select`` widget that uses a list of Dutch provinces as its list of
choices.
Iceland (``django.contrib.localflavor.is_``)
============================================
@ -304,7 +303,7 @@ ISIdNumberField
---------------
A form field that validates input as an Icelandic identification number
(kennitala). The format is XXXXXX-XXXX.
(kennitala). The format is XXXXXX-XXXX.
ISPhoneNumberField
------------------
@ -318,7 +317,6 @@ ISPostalCodeSelect
A ``Select`` widget that uses a list of Icelandic postal codes as its
choices.
India (``django.contrib.localflavor.in_``)
==========================================
@ -326,7 +324,7 @@ INStateField
------------
A form field that validates input as an Indian state/territory name or
abbreviation. Input is normalized to the standard two-letter vehicle
abbreviation. Input is normalized to the standard two-letter vehicle
registration abbreviation for the given state or territory.
INZipCodeField
@ -341,7 +339,6 @@ INStateSelect
A ``Select`` widget that uses a list of Indian states/territories as its
choices.
Italy (``django.contrib.localflavor.it``)
=========================================
@ -361,7 +358,7 @@ A form field that validates Italian VAT numbers (partita IVA).
ITZipCodeField
--------------
A form field that validates input as an Italian zip code. Valid codes
A form field that validates input as an Italian zip code. Valid codes
must have five digits.
ITProvinceSelect
@ -374,22 +371,20 @@ ITRegionSelect
A ``Select`` widget that uses a list of Italian regions as its choices.
Japan (``django.contrib.localflavor.jp``)
=========================================
JPPostalCodeField
-----------------
A form field that validates input as a Japanese postcode.
It accepts seven digits, with or without a hyphen.
A form field that validates input as a Japanese postcode. It accepts seven
digits, with or without a hyphen.
JPPrefectureSelect
------------------
A ``Select`` widget that uses a list of Japanese prefectures as its choices.
Mexico (``django.contrib.localflavor.mx``)
==========================================
@ -398,7 +393,6 @@ MXStateSelect
A ``Select`` widget that uses a list of Mexican states as its choices.
Norway (``django.contrib.localflavor.no``)
==========================================
@ -413,7 +407,7 @@ A form field that validates input as a Norwegian social security number
NOZipCodeField
--------------
A form field that validates input as a Norwegian zip code. Valid codes
A form field that validates input as a Norwegian zip code. Valid codes
have four digits.
NOMunicipalitySelect
@ -422,7 +416,6 @@ NOMunicipalitySelect
A ``Select`` widget that uses a list of Norwegian municipalities (fylker) as
its choices.
Peru (``django.contrib.localflavor.pe``)
========================================
@ -436,14 +429,13 @@ PERUCField
----------
A form field that validates input as an RUC (Registro Unico de
Contribuyentes) number. Valid RUC numbers have eleven digits.
Contribuyentes) number. Valid RUC numbers have 11 digits.
PEDepartmentSelect
------------------
A ``Select`` widget that uses a list of Peruvian Departments as its choices.
Poland (``django.contrib.localflavor.pl``)
==========================================
@ -459,7 +451,7 @@ PLNationalBusinessRegisterField
-------------------------------
A form field that validates input as a Polish National Official Business
Register Number (REGON_), having either seven or nine digits. The checksum
Register Number (REGON_), having either seven or nine digits. The checksum
algorithm used for REGONs is documented at
http://wipos.p.lodz.pl/zylla/ut/nip-rego.html.
@ -468,14 +460,14 @@ http://wipos.p.lodz.pl/zylla/ut/nip-rego.html.
PLPostalCodeField
-----------------
A form field that validates input as a Polish postal code. The valid format
A form field that validates input as a Polish postal code. The valid format
is XX-XXX, where X is a digit.
PLTaxNumberField
----------------
A form field that validates input as a Polish Tax Number (NIP). Valid
formats are XXX-XXX-XX-XX or XX-XX-XXX-XXX. The checksum algorithm used
A form field that validates input as a Polish Tax Number (NIP). Valid
formats are XXX-XXX-XX-XX or XX-XX-XXX-XXX. The checksum algorithm used
for NIPs is documented at http://wipos.p.lodz.pl/zylla/ut/nip-rego.html.
PLAdministrativeUnitSelect
@ -490,14 +482,13 @@ PLVoivodeshipSelect
A ``Select`` widget that uses a list of Polish voivodeships (administrative
provinces) as its choices.
Slovakia (``django.contrib.localflavor.sk``)
============================================
SKPostalCodeField
-----------------
A form field that validates input as a Slovak postal code. Valid formats
A form field that validates input as a Slovak postal code. Valid formats
are XXXXX or XXX XX, where X is a digit.
SKDistrictSelect
@ -510,24 +501,22 @@ SKRegionSelect
A ``Select`` widget that uses a list of Slovak regions as its choices.
South Africa (``django.contrib.localflavor.za``)
================================================
ZAIDField
---------
A form field that validates input as a South African ID number. Validation
A form field that validates input as a South African ID number. Validation
uses the Luhn checksum and a simplistic (i.e., not entirely accurate) check
for birth date.
ZAPostCodeField
---------------
A form field that validates input as a South African postcode. Valid
A form field that validates input as a South African postcode. Valid
postcodes must have four digits.
Spain (``django.contrib.localflavor.es``)
=========================================
@ -541,23 +530,23 @@ ESCCCField
----------
A form field that validates input as a Spanish bank account number (Codigo
Cuenta Cliente or CCC). A valid CCC number has the format
Cuenta Cliente or CCC). A valid CCC number has the format
EEEE-OOOO-CC-AAAAAAAAAA, where the E, O, C and A digits denote the entity,
office, checksum and account, respectively. The first checksum digit
validates the entity and office. The second checksum digit validates the
account. It is also valid to use a space as a delimiter, or to use no
office, checksum and account, respectively. The first checksum digit
validates the entity and office. The second checksum digit validates the
account. It is also valid to use a space as a delimiter, or to use no
delimiter.
ESPhoneNumberField
------------------
A form field that validates input as a Spanish phone number. Valid numbers
A form field that validates input as a Spanish phone number. Valid numbers
have nine digits, the first of which is 6, 8 or 9.
ESPostalCodeField
-----------------
A form field that validates input as a Spanish postal code. Valid codes
A form field that validates input as a Spanish postal code. Valid codes
have five digits, the first two being in the range 01 to 52, representing
the province.
@ -571,7 +560,6 @@ ESRegionSelect
A ``Select`` widget that uses a list of Spanish regions as its choices.
Switzerland (``django.contrib.localflavor.ch``)
===============================================
@ -585,14 +573,14 @@ have the correct checksums -- see http://adi.kousz.ch/artikel/IDCHE.htm.
CHPhoneNumberField
------------------
A form field that validates input as a Swiss phone number. The correct
format is 0XX XXX XX XX. 0XX.XXX.XX.XX and 0XXXXXXXXX validate but are
A form field that validates input as a Swiss phone number. The correct
format is 0XX XXX XX XX. 0XX.XXX.XX.XX and 0XXXXXXXXX validate but are
corrected to 0XX XXX XX XX.
CHZipCodeField
--------------
A form field that validates input as a Swiss zip code. Valid codes
A form field that validates input as a Swiss zip code. Valid codes
consist of four digits.
CHStateSelect
@ -600,7 +588,6 @@ CHStateSelect
A ``Select`` widget that uses a list of Swiss states as its choices.
United Kingdom (``django.contrib.localflavor.uk``)
==================================================
@ -611,6 +598,15 @@ A form field that validates input as a UK postcode. The regular
expression used is sourced from the schema for British Standard BS7666
address types at http://www.govtalk.gov.uk/gdsc/schemas/bs7666-v2-0.xsd.
UKCountySelect
--------------
A ``Select`` widget that uses a list of UK counties/regions as its choices.
UKNationSelect
--------------
A ``Select`` widget that uses a list of UK nations as its choices.
United States of America (``django.contrib.localflavor.us``)
============================================================
@ -626,13 +622,13 @@ USSocialSecurityNumberField
A form field that validates input as a U.S. Social Security Number (SSN).
A valid SSN must obey the following rules:
* Format of XXX-XX-XXXX
* No group of digits consisting entirely of zeroes
* Leading group of digits cannot be 666
* Number not in promotional block 987-65-4320 through 987-65-4329
* Number not one known to be invalid due to widespread promotional
use or distribution (e.g., the Woolworth's number or the 1962
promotional number)
* Format of XXX-XX-XXXX
* No group of digits consisting entirely of zeroes
* Leading group of digits cannot be 666
* Number not in promotional block 987-65-4320 through 987-65-4329
* Number not one known to be invalid due to widespread promotional
use or distribution (e.g., the Woolworth's number or the 1962
promotional number)
USStateField
------------
@ -644,11 +640,11 @@ for the given state.
USZipCodeField
--------------
A form field that validates input as a U.S. zip code. Valid formats are
A form field that validates input as a U.S. ZIP code. Valid formats are
XXXXX or XXXXX-XXXX.
USStateSelect
-------------
A form Select widget that uses a list of U.S. states/territories as its
A form ``Select`` widget that uses a list of U.S. states/territories as its
choices.

View File

@ -61,17 +61,18 @@ Adds a few conveniences for perfectionists:
settings.
If ``APPEND_SLASH`` is ``True`` and the initial URL doesn't end with a slash,
and it is not found in urlpatterns, a new URL is formed by appending a slash
at the end. If this new URL is found in urlpatterns, then an HTTP-redirect is
returned to this new URL; otherwise the initial URL is processed as usual.
and it is not found in the URLconf, then a new URL is formed by appending a
slash at the end. If this new URL is found in the URLconf, then Django
redirects the request to this new URL. Otherwise, the initial URL is
processed as usual.
So ``foo.com/bar`` will be redirected to ``foo.com/bar/`` if you do not
have a valid urlpattern for ``foo.com/bar``, and do have a valid urlpattern
for ``foo.com/bar/``.
For example, ``foo.com/bar`` will be redirected to ``foo.com/bar/`` if you
don't have a valid URL pattern for ``foo.com/bar`` but *do* have a valid
pattern for ``foo.com/bar/``.
**New in Django development version:** The behaviour of ``APPEND_SLASH`` has
changed slightly in the development version (it didn't used to check to see
if the pattern was matched in the URL patterns).
**New in Django development version:** The behavior of ``APPEND_SLASH`` has
changed slightly in the development version. It didn't used to check whether
the pattern was matched in the URLconf.
If ``PREPEND_WWW`` is ``True``, URLs that lack a leading "www." will be
redirected to the same URL with a leading "www."

View File

@ -618,7 +618,7 @@ statement for this field.
**New in Django development version**
The name of the database tablespace to use for this field's index, if
indeed this field is indexed. The default is the project's
this field is indexed. The default is the project's
``DEFAULT_INDEX_TABLESPACE`` setting, if set, or the ``db_tablespace``
of the model, if any. If the backend doesn't support tablespaces, this
option is ignored.

View File

@ -24,12 +24,11 @@ For example::
... model = Article
# Creating a form to add an article.
>>> article = Article()
>>> form = ArticleForm(article)
>>> form = ArticleForm()
# Creating a form to change an existing article.
>>> article = Article.objects.get(pk=1)
>>> form = ArticleForm(article)
>>> form = ArticleForm(instance=article)
Field types
-----------
@ -166,18 +165,23 @@ we'll discuss in a moment.)::
The ``save()`` method
---------------------
Every form produced by ``ModelForm`` also has a ``save()`` method. This
method creates and saves a database object from the data bound to the form.
A subclass of ``ModelForm`` also requires a model instance as the first
arument to its constructor. For example::
Every form produced by ``ModelForm`` also has a ``save()``
method. This method creates and saves a database object from the data
bound to the form. A subclass of ``ModelForm`` can accept an existing
model instance as the keyword argument ``instance``; if this is
supplied, ``save()`` will update that instance. If it's not supplied,
``save()`` will create a new instance of the specified model::
# Create a form instance from POST data.
>>> a = Article()
>>> f = ArticleForm(a, request.POST)
>>> f = ArticleForm(request.POST)
# Save a new Article object from the form's data.
>>> new_article = f.save()
# Create a form to edit an existing Article.
>>> a = Article.objects.get(pk=1)
>>> f = ArticleForm(instance=a)
Note that ``save()`` will raise a ``ValueError`` if the data in the form
doesn't validate -- i.e., ``if form.errors``.
@ -201,8 +205,7 @@ you've manually saved the instance produced by the form, you can invoke
``save_m2m()`` to save the many-to-many form data. For example::
# Create a form instance with POST data.
>>> a = Author()
>>> f = AuthorForm(a, request.POST)
>>> f = AuthorForm(request.POST)
# Create, but don't save the new author instance.
>>> new_author = f.save(commit=False)
@ -274,10 +277,10 @@ model fields:
any attempt to ``save()`` a ``ModelForm`` with missing fields will fail.
To avoid this failure, you must instantiate your model with initial values
for the missing, but required fields, or use ``save(commit=False)`` and
manually set anyextra required fields::
manually set any extra required fields::
instance = Instance(required_field='value')
form = InstanceForm(instance, request.POST)
form = InstanceForm(request.POST, instance=instance)
new_instance = form.save()
instance = form.save(commit=False)
@ -293,7 +296,7 @@ Overriding the default field types
----------------------------------
The default field types, as described in the "Field types" table above, are
sensible defaults; if you have a ``DateField`` in your model, chances are you'd
sensible defaults. If you have a ``DateField`` in your model, chances are you'd
want that to be represented as a ``DateField`` in your form. But
``ModelForm`` gives you the flexibility of changing the form field type
for a given model field. You do this by declaratively specifying fields like

View File

@ -766,7 +766,7 @@ label of each required field::
<form method="post" action="">
<dl>
{% for field in form %}
<dt>{{ field.label_tag }}{{ field.label }}{% if field.field.required %}*{% endif %}</dt>
<dt>{{ field.label_tag }}{% if field.field.required %}*{% endif %}</dt>
<dd>{{ field }}</dd>
{% if field.help_text %}<dd>{{ field.help_text }}</dd>{% endif %}
{% if field.errors %}<dd class="myerrors">{{ field.errors }}</dd>{% endif %}

View File

@ -156,6 +156,18 @@ Methods
Returns ``True`` or ``False``, designating whether ``request.GET`` or
``request.POST`` has the given key.
``get_host()``
**New in Django development version**
Returns the originating host of the request using information from the
``HTTP_X_FORWARDED_HOST`` and ``HTTP_HOST`` headers (in that order). If
they don't provide a value, the method uses a combination of
``SERVER_NAME`` and ``SERVER_PORT`` as detailed in `PEP 333`_.
.. _PEP 333: http://www.python.org/dev/peps/pep-0333/
Example: ``"127.0.0.1:8000"``
``get_full_path()``
Returns the ``path``, plus an appended query string, if applicable.
@ -452,7 +464,7 @@ types of HTTP responses. Like ``HttpResponse``, these subclasses live in
``HttpResponseNotModified``
The constructor doesn't take any arguments. Use this to designate that a
page hasn't been modified since the user's last request.
page hasn't been modified since the user's last request (status code 304).
``HttpResponseBadRequest``
**New in Django development version.**
@ -560,10 +572,10 @@ Three things to note about 404 views:
you must create a ``404.html`` template in the root of your
template directory. The default 404 view will use that template
for all 404 errors. The default 404 view will pass one variable
to the template: ``request_path``, which is the URL which
resulted in the 404.
to the template: ``request_path``, which is the URL that resulted
in the 404.
* If ``DEBUG`` is set to ``True`` (in your settings module) then your 404
* If ``DEBUG`` is set to ``True`` (in your settings module), then your 404
view will never be used, and the traceback will be displayed instead.
The 500 (server error) view

View File

@ -99,7 +99,7 @@ It implements the following standard dictionary methods:
* ``items()``
* ``setdefault()``
* ``setdefault()`` (**New in Django development version**)
It also has these three methods:

View File

@ -417,17 +417,21 @@ site manager(s).
DEFAULT_TABLESPACE
------------------
**New in Django development version**
Default: ``''`` (Empty string)
Default tablespace to use for models that do not specify one, if the
Default tablespace to use for models that don't specify one, if the
backend supports it.
DEFAULT_INDEX_TABLESPACE
------------------------
**New in Django development version**
Default: ``''`` (Empty string)
Default tablespace to use for indexes on fields that do not specify
Default tablespace to use for indexes on fields that don't specify
one, if the backend supports it.
DISALLOWED_USER_AGENTS
@ -977,8 +981,13 @@ TEST_DATABASE_NAME
Default: ``None``
The name of database to use when running the test suite. If a value of
``None`` is specified, the test database will use the name ``'test_' + settings.DATABASE_NAME``. See `Testing Django Applications`_.
The name of database to use when running the test suite.
If the default value (``None``) is used with the SQLite database engine, the
tests will use a memory resident database. For all other database engines the
test database will use the name ``'test_' + settings.DATABASE_NAME``.
See `Testing Django Applications`_.
.. _Testing Django Applications: ../testing/

View File

@ -234,6 +234,7 @@ request to the URL ``/rss/beats/0613/``:
``get_object()`` method, passing it the bits. In this case, bits is
``['0613']``. For a request to ``/rss/beats/0613/foo/bar/``, bits would
be ``['0613', 'foo', 'bar']``.
* ``get_object()`` is responsible for retrieving the given beat, from the
given ``bits``. In this case, it uses the Django database API to retrieve
the beat. Note that ``get_object()`` should raise
@ -243,6 +244,7 @@ request to the URL ``/rss/beats/0613/``:
raises ``Beat.DoesNotExist`` on failure, and ``Beat.DoesNotExist`` is a
subclass of ``ObjectDoesNotExist``. Raising ``ObjectDoesNotExist`` in
``get_object()`` tells Django to produce a 404 error for that request.
* To generate the feed's ``<title>``, ``<link>`` and ``<description>``,
Django uses the ``title()``, ``link()`` and ``description()`` methods. In
the previous example, they were simple string class attributes, but this
@ -258,9 +260,9 @@ request to the URL ``/rss/beats/0613/``:
Inside the ``link()`` method, we handle the possibility that ``obj``
might be ``None``, which can occur when the URL isn't fully specified. In
some cases, you might want to do something else in this case, which would
mean you'd need to check for ``obj`` existing in other methods as well
(the ``link()`` method is called very early in the feed generation
process, so is a good place to bail out early).
mean you'd need to check for ``obj`` existing in other methods as well.
(The ``link()`` method is called very early in the feed generation
process, so it's a good place to bail out early.)
* Finally, note that ``items()`` in this example also takes the ``obj``
argument. The algorithm for ``items`` is the same as described in the

View File

@ -565,17 +565,17 @@ autoescape
**New in Django development version**
Control the current auto-escaping behaviour. This tag takes either ``on`` or
Control the current auto-escaping behavior. This tag takes either ``on`` or
``off`` as an argument and that determines whether auto-escaping is in effect
inside the block.
When auto-escaping is in effect, all variable content has HTML escaping applied
to it before placing the result into the output (but after any filters have
been applied). This is equivalent to manually applying the ``escape`` filter
attached to each variable.
to each variable.
The only exceptions are variables that are already marked as 'safe' from
escaping, either by the code that populated the variable, or because it has
The only exceptions are variables that are already marked as "safe" from
escaping, either by the code that populated the variable, or because it has had
the ``safe`` or ``escape`` filters applied.
block
@ -1227,8 +1227,10 @@ Adds the arg to the value.
addslashes
~~~~~~~~~~
Adds slashes. Useful for passing strings to JavaScript, for example.
Adds slashes before quotes. Useful for escaping strings in CSV, for example.
**New in Django development version**: for escaping data in JavaScript strings,
use the `escapejs` filter instead.
capfirst
~~~~~~~~
@ -1302,6 +1304,15 @@ applied to the result will only result in one round of escaping being done. So
it is safe to use this function even in auto-escaping environments. If you want
multiple escaping passes to be applied, use the ``force_escape`` filter.
escapejs
~~~~~~~~
**New in Django development version**
Escapes characters for use in JavaScript strings. This does *not* make the
string safe for use in HTML, but does protect you from syntax errors when using
templates to generate JavaScript/JSON.
filesizeformat
~~~~~~~~~~~~~~
@ -1324,36 +1335,36 @@ floatformat
When used without an argument, rounds a floating-point number to one decimal
place -- but only if there's a decimal part to be displayed. For example:
======== ======================= ======
value Template Output
======== ======================= ======
34.23234 {{ value|floatformat }} 34.2
34.00000 {{ value|floatformat }} 34
34.26000 {{ value|floatformat }} 34.3
======== ======================= ======
============ =========================== ========
``value`` Template Output
============ =========================== ========
``34.23234`` ``{{ value|floatformat }}`` ``34.2``
``34.00000`` ``{{ value|floatformat }}`` ``34``
``34.26000`` ``{{ value|floatformat }}`` ``34.3``
============ =========================== ========
If used with a numeric integer argument, ``floatformat`` rounds a number to
that many decimal places. For example:
======== ========================= ======
value Template Output
======== ========================= ======
34.23234 {{ value|floatformat:3 }} 34.232
34.00000 {{ value|floatformat:3 }} 34.000
34.26000 {{ value|floatformat:3 }} 34.260
======== ========================= ======
============ ============================= ==========
``value`` Template Output
============ ============================= ==========
``34.23234`` ``{{ value|floatformat:3 }}`` ``34.232``
``34.00000`` ``{{ value|floatformat:3 }}`` ``34.000``
``34.26000`` ``{{ value|floatformat:3 }}`` ``34.260``
============ ============================= ==========
If the argument passed to ``floatformat`` is negative, it will round a number
to that many decimal places -- but only if there's a decimal part to be
displayed. For example:
======== ============================ ======
value Template Output
======== ============================ ======
34.23234 {{ value|floatformat:"-3" }} 34.232
34.00000 {{ value|floatformat:"-3" }} 34
34.26000 {{ value|floatformat:"-3" }} 34.260
======== ============================ ======
============ ================================ ==========
``value`` Template Output
============ ================================ ==========
``34.23234`` ``{{ value|floatformat:"-3" }}`` ``34.232``
``34.00000`` ``{{ value|floatformat:"-3" }}`` ``34``
``34.26000`` ``{{ value|floatformat:"-3" }}`` ``34.260``
============ ================================ ==========
Using ``floatformat`` with no argument is equivalent to using ``floatformat``
with an argument of ``-1``.

View File

@ -691,8 +691,8 @@ This way, you'll be able to pass, say, an integer to this filter, and it
won't cause an ``AttributeError`` (because integers don't have ``lower()``
methods).
Registering a custom filters
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Registering custom filters
~~~~~~~~~~~~~~~~~~~~~~~~~~
Once you've written your filter definition, you need to register it with
your ``Library`` instance, to make it available to Django's template language::

View File

@ -270,27 +270,21 @@ a test case, add the name of the test method to the label::
$ ./manage.py test animals.AnimalTestCase.testFluffyAnimals
Understanding the test output
-----------------------------
The test database
-----------------
When you run your tests, you'll see a number of messages as the test runner
prepares itself::
Tests that require a database (namely, model tests) will not use
your "real" (production) database. A separate, blank database is created
for the tests.
Creating test database...
Creating table myapp_animal
Creating table myapp_mineral
Loading 'initial_data' fixtures...
No fixtures found.
Regardless of whether the tests pass or fail, the test database is destroyed
when all the tests have been executed.
This tells you that the test runner is creating a test database -- a blank,
from-scratch database that it will use for any tests that happen to require a
database (namely, model tests).
Don't worry -- the test runner will not touch your "real" (production)
database. It creates a separate database purely for the tests. This test
database gets its name by prepending ``test_`` to the value of the
``DATABASE_NAME`` setting. If you want to use a different name, specify the
``TEST_DATABASE_NAME`` setting.
By default this test database gets its name by prepending ``test_`` to the
value of the ``DATABASE_NAME`` setting. When using the SQLite database engine
the tests will by default use an in-memory database (i.e., the database will be
created in memory, bypassing the filesystem entirely!). If you want to use a
different database name, specify the ``TEST_DATABASE_NAME`` setting.
Aside from using a separate database, the test runner will otherwise use all of
the same database settings you have in your settings file: ``DATABASE_ENGINE``,
@ -306,6 +300,22 @@ settings_ documentation for details of these advanced settings.
.. _settings: ../settings/
Understanding the test output
-----------------------------
When you run your tests, you'll see a number of messages as the test runner
prepares itself. You can control the level of detail of these messages with the
``verbosity`` option on the command line::
Creating test database...
Creating table myapp_animal
Creating table myapp_mineral
Loading 'initial_data' fixtures...
No fixtures found.
This tells you that the test runner is creating a test database, as described
in the previous section.
Once the test database has been created, Django will run your tests.
If everything goes well, you'll see something like this::
@ -349,9 +359,6 @@ failed and erroneous tests. If all the tests pass, the return code is 0. This
feature is useful if you're using the test-runner script in a shell script and
need to test for success or failure at that level.
Regardless of whether the tests pass or fail, the test database is destroyed when
all the tests have been executed.
Testing tools
=============

View File

@ -18,42 +18,42 @@ class TaggedItem(models.Model):
tag = models.SlugField()
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey()
class Meta:
ordering = ["tag"]
def __unicode__(self):
return self.tag
class Animal(models.Model):
common_name = models.CharField(max_length=150)
latin_name = models.CharField(max_length=150)
tags = generic.GenericRelation(TaggedItem)
def __unicode__(self):
return self.common_name
class Vegetable(models.Model):
name = models.CharField(max_length=150)
is_yucky = models.BooleanField(default=True)
tags = generic.GenericRelation(TaggedItem)
def __unicode__(self):
return self.name
class Mineral(models.Model):
name = models.CharField(max_length=150)
hardness = models.PositiveSmallIntegerField()
# note the lack of an explicit GenericRelation here...
def __unicode__(self):
return self.name
__test__ = {'API_TESTS':"""
# Create the world in 7 lines of code...
>>> lion = Animal(common_name="Lion", latin_name="Panthera leo")
@ -117,13 +117,13 @@ __test__ = {'API_TESTS':"""
>>> [(t.tag, t.content_type, t.object_id) for t in TaggedItem.objects.all()]
[(u'clearish', <ContentType: mineral>, 1), (u'fatty', <ContentType: vegetable>, 2), (u'salty', <ContentType: vegetable>, 2), (u'shiny', <ContentType: animal>, 2)]
# If Generic Relation is not explicitly defined, any related objects
# If Generic Relation is not explicitly defined, any related objects
# remain after deletion of the source object.
>>> quartz.delete()
>>> [(t.tag, t.content_type, t.object_id) for t in TaggedItem.objects.all()]
[(u'clearish', <ContentType: mineral>, 1), (u'fatty', <ContentType: vegetable>, 2), (u'salty', <ContentType: vegetable>, 2), (u'shiny', <ContentType: animal>, 2)]
# If you delete a tag, the objects using the tag are unaffected
# If you delete a tag, the objects using the tag are unaffected
# (other than losing a tag)
>>> tag = TaggedItem.objects.get(id=1)
>>> tag.delete()
@ -132,4 +132,8 @@ __test__ = {'API_TESTS':"""
>>> [(t.tag, t.content_type, t.object_id) for t in TaggedItem.objects.all()]
[(u'clearish', <ContentType: mineral>, 1), (u'salty', <ContentType: vegetable>, 2), (u'shiny', <ContentType: animal>, 2)]
>>> ctype = ContentType.objects.get_for_model(lion)
>>> Animal.objects.filter(tags__content_type=ctype)
[<Animal: Platypus>]
"""}

View File

@ -143,7 +143,7 @@ familiar with the mechanics.
... model = Article
Traceback (most recent call last):
...
ImproperlyConfigured: BadForm defines more than one model.
ImproperlyConfigured: BadForm defines a different model than its parent.
>>> class ArticleForm(ModelForm):
... class Meta:
@ -155,6 +155,12 @@ Traceback (most recent call last):
...
ImproperlyConfigured: BadForm's base classes define more than one model.
This one is OK since the subclass specifies the same model as the parent.
>>> class SubCategoryForm(CategoryForm):
... class Meta:
... model = Category
# Old form_for_x tests #######################################################
@ -167,7 +173,7 @@ ImproperlyConfigured: BadForm's base classes define more than one model.
>>> class CategoryForm(ModelForm):
... class Meta:
... model = Category
>>> f = CategoryForm(Category())
>>> f = CategoryForm()
>>> print f
<tr><th><label for="id_name">Name:</label></th><td><input id="id_name" type="text" name="name" maxlength="20" /></td></tr>
<tr><th><label for="id_slug">Slug:</label></th><td><input id="id_slug" type="text" name="slug" maxlength="20" /></td></tr>
@ -179,13 +185,13 @@ ImproperlyConfigured: BadForm's base classes define more than one model.
>>> print f['name']
<input id="id_name" type="text" name="name" maxlength="20" />
>>> f = CategoryForm(Category(), auto_id=False)
>>> f = CategoryForm(auto_id=False)
>>> print f.as_ul()
<li>Name: <input type="text" name="name" maxlength="20" /></li>
<li>Slug: <input type="text" name="slug" maxlength="20" /></li>
<li>The URL: <input type="text" name="url" maxlength="40" /></li>
>>> f = CategoryForm(Category(), {'name': 'Entertainment', 'slug': 'entertainment', 'url': 'entertainment'})
>>> f = CategoryForm({'name': 'Entertainment', 'slug': 'entertainment', 'url': 'entertainment'})
>>> f.is_valid()
True
>>> f.cleaned_data
@ -196,7 +202,7 @@ True
>>> Category.objects.all()
[<Category: Entertainment>]
>>> f = CategoryForm(Category(), {'name': "It's a test", 'slug': 'its-test', 'url': 'test'})
>>> f = CategoryForm({'name': "It's a test", 'slug': 'its-test', 'url': 'test'})
>>> f.is_valid()
True
>>> f.cleaned_data
@ -210,7 +216,7 @@ True
If you call save() with commit=False, then it will return an object that
hasn't yet been saved to the database. In this case, it's up to you to call
save() on the resulting model instance.
>>> f = CategoryForm(Category(), {'name': 'Third test', 'slug': 'third-test', 'url': 'third'})
>>> f = CategoryForm({'name': 'Third test', 'slug': 'third-test', 'url': 'third'})
>>> f.is_valid()
True
>>> f.cleaned_data
@ -225,7 +231,7 @@ True
[<Category: Entertainment>, <Category: It's a test>, <Category: Third test>]
If you call save() with invalid data, you'll get a ValueError.
>>> f = CategoryForm(Category(), {'name': '', 'slug': '', 'url': 'foo'})
>>> f = CategoryForm({'name': '', 'slug': '', 'url': 'foo'})
>>> f.errors
{'name': [u'This field is required.'], 'slug': [u'This field is required.']}
>>> f.cleaned_data
@ -236,7 +242,7 @@ AttributeError: 'CategoryForm' object has no attribute 'cleaned_data'
Traceback (most recent call last):
...
ValueError: The Category could not be created because the data didn't validate.
>>> f = CategoryForm(Category(), {'name': '', 'slug': '', 'url': 'foo'})
>>> f = CategoryForm({'name': '', 'slug': '', 'url': 'foo'})
>>> f.save()
Traceback (most recent call last):
...
@ -253,7 +259,7 @@ fields with the 'choices' attribute are represented by a ChoiceField.
>>> class ArticleForm(ModelForm):
... class Meta:
... model = Article
>>> f = ArticleForm(Article(), auto_id=False)
>>> f = ArticleForm(auto_id=False)
>>> print f
<tr><th>Headline:</th><td><input type="text" name="headline" maxlength="50" /></td></tr>
<tr><th>Slug:</th><td><input type="text" name="slug" maxlength="50" /></td></tr>
@ -286,7 +292,7 @@ from the form can't provide a value for that field!
... class Meta:
... model = Article
... fields = ('headline','pub_date')
>>> f = PartialArticleForm(Article(), auto_id=False)
>>> f = PartialArticleForm(auto_id=False)
>>> print f
<tr><th>Headline:</th><td><input type="text" name="headline" maxlength="50" /></td></tr>
<tr><th>Pub date:</th><td><input type="text" name="pub_date" /></td></tr>
@ -298,7 +304,7 @@ current values are inserted as 'initial' data in each Field.
>>> class RoykoForm(ModelForm):
... class Meta:
... model = Writer
>>> f = RoykoForm(w, auto_id=False)
>>> f = RoykoForm(auto_id=False, instance=w)
>>> print f
<tr><th>Name:</th><td><input type="text" name="name" value="Mike Royko" maxlength="50" /><br />Use both first and last names.</td></tr>
@ -309,7 +315,7 @@ current values are inserted as 'initial' data in each Field.
>>> class TestArticleForm(ModelForm):
... class Meta:
... model = Article
>>> f = TestArticleForm(art, auto_id=False)
>>> f = TestArticleForm(auto_id=False, instance=art)
>>> print f.as_ul()
<li>Headline: <input type="text" name="headline" value="Test article" maxlength="50" /></li>
<li>Slug: <input type="text" name="slug" value="test-article" maxlength="50" /></li>
@ -331,7 +337,7 @@ current values are inserted as 'initial' data in each Field.
<option value="2">It&#39;s a test</option>
<option value="3">Third test</option>
</select> Hold down "Control", or "Command" on a Mac, to select more than one.</li>
>>> f = TestArticleForm(art, {'headline': u'Test headline', 'slug': 'test-headline', 'pub_date': u'1984-02-06', 'writer': u'1', 'article': 'Hello.'})
>>> f = TestArticleForm({'headline': u'Test headline', 'slug': 'test-headline', 'pub_date': u'1984-02-06', 'writer': u'1', 'article': 'Hello.'}, instance=art)
>>> f.is_valid()
True
>>> test_art = f.save()
@ -347,7 +353,7 @@ by specifying a 'fields' argument to form_for_instance.
... class Meta:
... model = Article
... fields=('headline', 'slug', 'pub_date')
>>> f = PartialArticleForm(art, {'headline': u'New headline', 'slug': 'new-headline', 'pub_date': u'1988-01-04'}, auto_id=False)
>>> f = PartialArticleForm({'headline': u'New headline', 'slug': 'new-headline', 'pub_date': u'1988-01-04'}, auto_id=False, instance=art)
>>> print f.as_ul()
<li>Headline: <input type="text" name="headline" value="New headline" maxlength="50" /></li>
<li>Slug: <input type="text" name="slug" value="new-headline" maxlength="50" /></li>
@ -370,7 +376,7 @@ Add some categories and test the many-to-many form output.
>>> class TestArticleForm(ModelForm):
... class Meta:
... model = Article
>>> f = TestArticleForm(new_art, auto_id=False)
>>> f = TestArticleForm(auto_id=False, instance=new_art)
>>> print f.as_ul()
<li>Headline: <input type="text" name="headline" value="New headline" maxlength="50" /></li>
<li>Slug: <input type="text" name="slug" value="new-headline" maxlength="50" /></li>
@ -393,8 +399,8 @@ Add some categories and test the many-to-many form output.
<option value="3">Third test</option>
</select> Hold down "Control", or "Command" on a Mac, to select more than one.</li>
>>> f = TestArticleForm(new_art, {'headline': u'New headline', 'slug': u'new-headline', 'pub_date': u'1988-01-04',
... 'writer': u'1', 'article': u'Hello.', 'categories': [u'1', u'2']})
>>> f = TestArticleForm({'headline': u'New headline', 'slug': u'new-headline', 'pub_date': u'1988-01-04',
... 'writer': u'1', 'article': u'Hello.', 'categories': [u'1', u'2']}, instance=new_art)
>>> new_art = f.save()
>>> new_art.id
1
@ -403,8 +409,8 @@ Add some categories and test the many-to-many form output.
[<Category: Entertainment>, <Category: It's a test>]
Now, submit form data with no categories. This deletes the existing categories.
>>> f = TestArticleForm(new_art, {'headline': u'New headline', 'slug': u'new-headline', 'pub_date': u'1988-01-04',
... 'writer': u'1', 'article': u'Hello.'})
>>> f = TestArticleForm({'headline': u'New headline', 'slug': u'new-headline', 'pub_date': u'1988-01-04',
... 'writer': u'1', 'article': u'Hello.'}, instance=new_art)
>>> new_art = f.save()
>>> new_art.id
1
@ -416,7 +422,7 @@ Create a new article, with categories, via the form.
>>> class ArticleForm(ModelForm):
... class Meta:
... model = Article
>>> f = ArticleForm(Article(), {'headline': u'The walrus was Paul', 'slug': u'walrus-was-paul', 'pub_date': u'1967-11-01',
>>> f = ArticleForm({'headline': u'The walrus was Paul', 'slug': u'walrus-was-paul', 'pub_date': u'1967-11-01',
... 'writer': u'1', 'article': u'Test.', 'categories': [u'1', u'2']})
>>> new_art = f.save()
>>> new_art.id
@ -429,7 +435,7 @@ Create a new article, with no categories, via the form.
>>> class ArticleForm(ModelForm):
... class Meta:
... model = Article
>>> f = ArticleForm(Article(), {'headline': u'The walrus was Paul', 'slug': u'walrus-was-paul', 'pub_date': u'1967-11-01',
>>> f = ArticleForm({'headline': u'The walrus was Paul', 'slug': u'walrus-was-paul', 'pub_date': u'1967-11-01',
... 'writer': u'1', 'article': u'Test.'})
>>> new_art = f.save()
>>> new_art.id
@ -443,7 +449,7 @@ The m2m data won't be saved until save_m2m() is invoked on the form.
>>> class ArticleForm(ModelForm):
... class Meta:
... model = Article
>>> f = ArticleForm(Article(), {'headline': u'The walrus was Paul', 'slug': 'walrus-was-paul', 'pub_date': u'1967-11-01',
>>> f = ArticleForm({'headline': u'The walrus was Paul', 'slug': 'walrus-was-paul', 'pub_date': u'1967-11-01',
... 'writer': u'1', 'article': u'Test.', 'categories': [u'1', u'2']})
>>> new_art = f.save(commit=False)
@ -474,7 +480,7 @@ existing Category instance.
<Category: Third test>
>>> cat.id
3
>>> form = ShortCategory(cat, {'name': 'Third', 'slug': 'third', 'url': '3rd'})
>>> form = ShortCategory({'name': 'Third', 'slug': 'third', 'url': '3rd'}, instance=cat)
>>> form.save()
<Category: Third>
>>> Category.objects.get(id=3)
@ -486,7 +492,7 @@ the data in the database when the form is instantiated.
>>> class ArticleForm(ModelForm):
... class Meta:
... model = Article
>>> f = ArticleForm(Article(), auto_id=False)
>>> f = ArticleForm(auto_id=False)
>>> print f.as_ul()
<li>Headline: <input type="text" name="headline" maxlength="50" /></li>
<li>Slug: <input type="text" name="slug" maxlength="50" /></li>
@ -690,7 +696,7 @@ ValidationError: [u'Select a valid choice. 4 is not one of the available choices
>>> class PhoneNumberForm(ModelForm):
... class Meta:
... model = PhoneNumber
>>> f = PhoneNumberForm(PhoneNumber(), {'phone': '(312) 555-1212', 'description': 'Assistance'})
>>> f = PhoneNumberForm({'phone': '(312) 555-1212', 'description': 'Assistance'})
>>> f.is_valid()
True
>>> f.cleaned_data

View File

@ -218,3 +218,41 @@ None
3.4
"""}
try:
import yaml
__test__['YAML'] = """
# Create some data:
>>> articles = Article.objects.all().order_by("id")[:2]
>>> from django.core import serializers
# test if serial
>>> serialized = serializers.serialize("yaml", articles)
>>> print serialized
- fields:
author: 2
categories: [3, 1]
headline: Just kidding; I love TV poker
pub_date: 2006-06-16 11:00:00
model: serializers.article
pk: 1
- fields:
author: 1
categories: [2, 3]
headline: Time to reform copyright
pub_date: 2006-06-16 13:00:11
model: serializers.article
pk: 2
<BLANKLINE>
>>> obs = list(serializers.deserialize("yaml", serialized))
>>> for i in obs:
... print i
<DeserializedObject: Just kidding; I love TV poker>
<DeserializedObject: Time to reform copyright>
"""
except ImportError: pass

View File

@ -3,8 +3,8 @@
# Unit tests for cache framework
# Uses whatever cache backend is set in the test settings file.
import time, unittest
import time
import unittest
from django.core.cache import cache
from django.utils.cache import patch_vary_headers
from django.http import HttpResponse
@ -27,7 +27,7 @@ class Cache(unittest.TestCase):
cache.add("addkey1", "value")
cache.add("addkey1", "newvalue")
self.assertEqual(cache.get("addkey1"), "value")
def test_non_existent(self):
# get with non-existent keys
self.assertEqual(cache.get("does_not_exist"), None)
@ -76,10 +76,16 @@ class Cache(unittest.TestCase):
self.assertEqual(cache.get("stuff"), stuff)
def test_expiration(self):
# expiration
cache.set('expire', 'very quickly', 1)
time.sleep(2)
self.assertEqual(cache.get("expire"), None)
cache.set('expire1', 'very quickly', 1)
cache.set('expire2', 'very quickly', 1)
cache.set('expire3', 'very quickly', 1)
time.sleep(2)
self.assertEqual(cache.get("expire1"), None)
cache.add("expire2", "newvalue")
self.assertEqual(cache.get("expire2"), "newvalue")
self.assertEqual(cache.has_key("expire3"), False)
def test_unicode(self):
stuff = {
@ -92,6 +98,44 @@ class Cache(unittest.TestCase):
cache.set(key, value)
self.assertEqual(cache.get(key), value)
import os
import md5
import shutil
import tempfile
from django.core.cache.backends.filebased import CacheClass as FileCache
class FileBasedCacheTests(unittest.TestCase):
"""
Specific test cases for the file-based cache.
"""
def setUp(self):
self.dirname = tempfile.mktemp()
os.mkdir(self.dirname)
self.cache = FileCache(self.dirname, {})
def tearDown(self):
shutil.rmtree(self.dirname)
def test_hashing(self):
"""Test that keys are hashed into subdirectories correctly"""
self.cache.set("foo", "bar")
keyhash = md5.new("foo").hexdigest()
keypath = os.path.join(self.dirname, keyhash[:2], keyhash[2:4], keyhash[4:])
self.assert_(os.path.exists(keypath))
def test_subdirectory_removal(self):
"""
Make sure that the created subdirectories are correctly removed when empty.
"""
self.cache.set("foo", "bar")
keyhash = md5.new("foo").hexdigest()
keypath = os.path.join(self.dirname, keyhash[:2], keyhash[2:4], keyhash[4:])
self.assert_(os.path.exists(keypath))
self.cache.delete("foo")
self.assert_(not os.path.exists(keypath))
self.assert_(not os.path.exists(os.path.dirname(keypath)))
self.assert_(not os.path.exists(os.path.dirname(os.path.dirname(keypath))))
class CacheUtils(unittest.TestCase):
"""TestCase for django.utils.cache functions."""

View File

@ -49,6 +49,18 @@ u'\\\\ : backslashes, too'
>>> capfirst(u'hello world')
u'Hello world'
>>> escapejs(u'"double quotes" and \'single quotes\'')
u'\\"double quotes\\" and \\\'single quotes\\\''
>>> escapejs(ur'\ : backslashes, too')
u'\\\\ : backslashes, too'
>>> escapejs(u'and lots of whitespace: \r\n\t\v\f\b')
u'and lots of whitespace: \\r\\n\\t\\v\\f\\b'
>>> escapejs(ur'<script>and this</script>')
u'<script>and this<\\/script>'
>>> fix_ampersands(u'Jack & Jill & Jeroboam')
u'Jack &amp; Jill &amp; Jeroboam'

View File

@ -41,7 +41,7 @@ Strict RUT usage (does not allow imposible values)
>>> rut.clean('11-6')
Traceback (most recent call last):
...
ValidationError: [u'Enter valid a Chilean RUT. The format is XX.XXX.XXX-X.']
ValidationError: [u'Enter a valid Chilean RUT. The format is XX.XXX.XXX-X.']
# valid format, bad verifier.
>>> rut.clean('11.111.111-0')
@ -53,17 +53,17 @@ ValidationError: [u'The Chilean RUT is not valid.']
>>> rut.clean('767484100')
Traceback (most recent call last):
...
ValidationError: [u'Enter valid a Chilean RUT. The format is XX.XXX.XXX-X.']
ValidationError: [u'Enter a valid Chilean RUT. The format is XX.XXX.XXX-X.']
>>> rut.clean('78.412.790-7')
u'78.412.790-7'
>>> rut.clean('8.334.6043')
Traceback (most recent call last):
...
ValidationError: [u'Enter valid a Chilean RUT. The format is XX.XXX.XXX-X.']
ValidationError: [u'Enter a valid Chilean RUT. The format is XX.XXX.XXX-X.']
>>> rut.clean('76793310-K')
Traceback (most recent call last):
...
ValidationError: [u'Enter valid a Chilean RUT. The format is XX.XXX.XXX-X.']
ValidationError: [u'Enter a valid Chilean RUT. The format is XX.XXX.XXX-X.']
## CLRegionSelect #########################################################
>>> from django.contrib.localflavor.cl.forms import CLRegionSelect

View File

@ -12,13 +12,15 @@ u'BT32 4PX'
>>> f.clean('GIR 0AA')
u'GIR 0AA'
>>> f.clean('BT324PX')
Traceback (most recent call last):
...
ValidationError: [u'Enter a postcode. A space is required between the two postcode parts.']
u'BT32 4PX'
>>> f.clean('1NV 4L1D')
Traceback (most recent call last):
...
ValidationError: [u'Enter a postcode. A space is required between the two postcode parts.']
ValidationError: [u'Enter a valid postcode.']
>>> f.clean('1NV4L1D')
Traceback (most recent call last):
...
ValidationError: [u'Enter a valid postcode.']
>>> f.clean(None)
Traceback (most recent call last):
...
@ -27,7 +29,20 @@ ValidationError: [u'This field is required.']
Traceback (most recent call last):
...
ValidationError: [u'This field is required.']
>>> f.clean(' so11aa ')
u'SO1 1AA'
>>> f.clean(' so1 1aa ')
u'SO1 1AA'
>>> f.clean('G2 3wt')
u'G2 3WT'
>>> f.clean('EC1A 1BB')
u'EC1A 1BB'
>>> f.clean('Ec1a1BB')
u'EC1A 1BB'
>>> f.clean(' b0gUS')
Traceback (most recent call last):
...
ValidationError: [u'Enter a valid postcode.']
>>> f = UKPostcodeField(required=False)
>>> f.clean('BT32 4PX')
u'BT32 4PX'
@ -36,11 +51,9 @@ u'GIR 0AA'
>>> f.clean('1NV 4L1D')
Traceback (most recent call last):
...
ValidationError: [u'Enter a postcode. A space is required between the two postcode parts.']
ValidationError: [u'Enter a valid postcode.']
>>> f.clean('BT324PX')
Traceback (most recent call last):
...
ValidationError: [u'Enter a postcode. A space is required between the two postcode parts.']
u'BT32 4PX'
>>> f.clean(None)
u''
>>> f.clean('')

View File

@ -391,9 +391,45 @@ u'\ufffd'
>>> q.getlist('foo')
[u'bar', u'\ufffd']
######################################
# HttpResponse with Unicode headers #
######################################
>>> r = HttpResponse()
If we insert a unicode value it will be converted to an ascii
string. This makes sure we comply with the HTTP specifications.
>>> r['value'] = u'test value'
>>> isinstance(r['value'], str)
True
An error is raised When a unicode object with non-ascii is assigned.
>>> r['value'] = u't\xebst value' # doctest:+ELLIPSIS
Traceback (most recent call last):
...
UnicodeEncodeError: ..., HTTP response headers must be in US-ASCII format
The response also converts unicode keys to strings.
>>> r[u'test'] = 'testing key'
>>> l = list(r.items())
>>> l.sort()
>>> l[1]
('test', 'testing key')
It will also raise errors for keys with non-ascii data.
>>> r[u't\xebst'] = 'testing key' # doctest:+ELLIPSIS
Traceback (most recent call last):
...
UnicodeEncodeError: ..., HTTP response headers must be in US-ASCII format
"""
from django.http import QueryDict
from django.http import QueryDict, HttpResponse
if __name__ == "__main__":
import doctest

View File

@ -22,12 +22,12 @@ Don't print out the deprecation warnings during testing.
>>> legacy_maxlength(10, 12)
Traceback (most recent call last):
...
TypeError: field can not take both the max_length argument and the legacy maxlength argument.
TypeError: Field cannot take both the max_length argument and the legacy maxlength argument.
>>> legacy_maxlength(0, 10)
Traceback (most recent call last):
...
TypeError: field can not take both the max_length argument and the legacy maxlength argument.
TypeError: Field cannot take both the max_length argument and the legacy maxlength argument.
>>> legacy_maxlength(0, None)
0
@ -48,7 +48,7 @@ TypeError: field can not take both the max_length argument and the legacy maxlen
>>> fields.Field(maxlength=10, max_length=15)
Traceback (most recent call last):
...
TypeError: field can not take both the max_length argument and the legacy maxlength argument.
TypeError: Field cannot take both the max_length argument and the legacy maxlength argument.
# Test max_length
>>> new.max_length

View File

@ -11,6 +11,7 @@ class Article(models.Model):
pub_date = models.DateTimeField()
status = models.IntegerField(blank=True, null=True, choices=CHOICES)
misc_data = models.CharField(max_length=100, blank=True)
article_text = models.TextField()
class Meta:
ordering = ('pub_date','headline')
@ -41,5 +42,14 @@ Empty strings should be returned as Unicode
>>> a2 = Article.objects.get(pk=a.id)
>>> a2.misc_data
u''
# TextFields can hold more than 4000 characters (this was broken in Oracle).
>>> a3 = Article(headline="Really, really big", pub_date=datetime.now())
>>> a3.article_text = "ABCDE" * 1000
>>> a3.save()
>>> a4 = Article.objects.get(pk=a3.id)
>>> len(a4.article_text)
5000
"""
}

View File

@ -108,8 +108,8 @@ def get_filter_tests():
'filter-urlize05': ('{% autoescape off %}{{ a|urlize }}{% endautoescape %}', {"a": "<script>alert('foo')</script>"}, "<script>alert('foo')</script>"),
'filter-urlize06': ('{{ a|urlize }}', {"a": "<script>alert('foo')</script>"}, '&lt;script&gt;alert(&#39;foo&#39;)&lt;/script&gt;'),
'filter-urlizetrunc01': ('{% autoescape off %}{{ a|urlizetrunc:"8" }} {{ b|urlizetrunc:"8" }}{% endautoescape %}', {"a": "http://example.com/x=&y=", "b": mark_safe("http://example.com?x=&y=")}, u'<a href="http://example.com/x=&y=" rel="nofollow">http:...</a> <a href="http://example.com?x=&y=" rel="nofollow">http:...</a>'),
'filter-urlizetrunc02': ('{{ a|urlizetrunc:"8" }} {{ b|urlizetrunc:"8" }}', {"a": "http://example.com/x=&y=", "b": mark_safe("http://example.com?x=&y=")}, u'<a href="http://example.com/x=&y=" rel="nofollow">http:...</a> <a href="http://example.com?x=&y=" rel="nofollow">http:...</a>'),
'filter-urlizetrunc01': ('{% autoescape off %}{{ a|urlizetrunc:"8" }} {{ b|urlizetrunc:"8" }}{% endautoescape %}', {"a": '"Unsafe" http://example.com/x=&y=', "b": mark_safe('&quot;Safe&quot; http://example.com?x=&y=')}, u'"Unsafe" <a href="http://example.com/x=&y=" rel="nofollow">http:...</a> &quot;Safe&quot; <a href="http://example.com?x=&y=" rel="nofollow">http:...</a>'),
'filter-urlizetrunc02': ('{{ a|urlizetrunc:"8" }} {{ b|urlizetrunc:"8" }}', {"a": '"Unsafe" http://example.com/x=&y=', "b": mark_safe('&quot;Safe&quot; http://example.com?x=&y=')}, u'&quot;Unsafe&quot; <a href="http://example.com/x=&y=" rel="nofollow">http:...</a> &quot;Safe&quot; <a href="http://example.com?x=&y=" rel="nofollow">http:...</a>'),
'filter-wordcount01': ('{% autoescape off %}{{ a|wordcount }} {{ b|wordcount }}{% endautoescape %}', {"a": "a & b", "b": mark_safe("a &amp; b")}, "3 3"),
'filter-wordcount02': ('{{ a|wordcount }} {{ b|wordcount }}', {"a": "a & b", "b": mark_safe("a &amp; b")}, "3 3"),

View File

@ -0,0 +1 @@
An unknown file extension.

View File

@ -13,11 +13,15 @@ class StaticTests(TestCase):
response = self.client.get('/views/site_media/%s' % filename)
file = open(path.join(media_dir, filename))
self.assertEquals(file.read(), response.content)
self.assertEquals(len(response.content), int(response['Content-Length']))
def test_unknown_mime_type(self):
response = self.client.get('/views/site_media/file.unknown')
self.assertEquals('application/octet-stream', response['Content-Type'])
def test_copes_with_empty_path_component(self):
file_name = 'file.txt'
response = self.client.get('/views/site_media//%s' % file_name)
file = open(path.join(media_dir, file_name))
self.assertEquals(file.read(), response.content)

View File

@ -93,6 +93,7 @@ def django_tests(verbosity, interactive, test_labels):
old_root_urlconf = settings.ROOT_URLCONF
old_template_dirs = settings.TEMPLATE_DIRS
old_use_i18n = settings.USE_I18N
old_login_url = settings.LOGIN_URL
old_language_code = settings.LANGUAGE_CODE
old_middleware_classes = settings.MIDDLEWARE_CLASSES
@ -102,6 +103,7 @@ def django_tests(verbosity, interactive, test_labels):
settings.TEMPLATE_DIRS = (os.path.join(os.path.dirname(__file__), TEST_TEMPLATE_DIR),)
settings.USE_I18N = True
settings.LANGUAGE_CODE = 'en'
settings.LOGIN_URL = '/accounts/login/'
settings.MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
@ -154,6 +156,7 @@ def django_tests(verbosity, interactive, test_labels):
settings.TEMPLATE_DIRS = old_template_dirs
settings.USE_I18N = old_use_i18n
settings.LANGUAGE_CODE = old_language_code
settings.LOGIN_URL = old_login_url
settings.MIDDLEWARE_CLASSES = old_middleware_classes
if __name__ == "__main__":