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:
parent
3f494f1823
commit
f4c7a0dcb6
3
AUTHORS
3
AUTHORS
@ -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>
|
||||
|
@ -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)
|
||||
|
||||
|
Binary file not shown.
@ -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"
|
||||
|
Binary file not shown.
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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'}
|
||||
|
@ -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()
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
|
@ -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):
|
||||
|
@ -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):
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 )
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -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)
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -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'])
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -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)
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
110
django/core/cache/backends/filebased.py
vendored
110
django/core/cache/backends/filebased.py
vendored
@ -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)
|
||||
|
||||
|
59
django/core/cache/backends/locmem.py
vendored
59
django/core/cache/backends/locmem.py
vendored
@ -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:
|
||||
|
@ -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):
|
||||
|
@ -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 = ''
|
||||
|
@ -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)
|
||||
|
@ -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:
|
||||
|
@ -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()))))
|
||||
|
@ -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()
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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 = []
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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):
|
||||
|
@ -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):
|
||||
|
@ -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'):
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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 ``&`` 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)
|
||||
|
@ -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 %}
|
||||
|
@ -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.
|
||||
|
@ -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 = ['(', '<', '<']
|
||||
TRAILING_PUNCTUATION = ['.', ',', ')', '>', '\n', '>']
|
||||
|
||||
# list of possible strings used for bullets in bulleted lists
|
||||
# List of possible strings used for bullets in bulleted lists.
|
||||
DOTS = ['·', '*', '\xe2\x80\xa2', '•', '•', '•']
|
||||
|
||||
unencoded_ampersands_re = re.compile(r'&(?!(\w+|#\d+);)')
|
||||
@ -28,7 +28,7 @@ trailing_empty_content_re = re.compile(r'(?:<p>(?: |\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('&', '&').replace('<', '<').replace('>', '>').replace('"', '"').replace("'", '''))
|
||||
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('&', 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
|
||||
|
@ -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.
|
||||
|
@ -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; }
|
||||
|
@ -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 = """
|
||||
|
@ -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
|
||||
=============
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
~~~~~~~~
|
||||
|
||||
|
@ -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
|
||||
|
@ -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/
|
||||
|
@ -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.
|
||||
|
@ -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."
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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 %}
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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/
|
||||
|
||||
|
@ -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
|
||||
|
@ -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``.
|
||||
|
@ -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::
|
||||
|
@ -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
|
||||
=============
|
||||
|
||||
|
@ -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>]
|
||||
|
||||
"""}
|
||||
|
@ -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'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
|
||||
|
@ -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
|
||||
|
||||
|
58
tests/regressiontests/cache/tests.py
vendored
58
tests/regressiontests/cache/tests.py
vendored
@ -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."""
|
||||
|
@ -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 & Jill & Jeroboam'
|
||||
|
||||
|
@ -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
|
||||
|
@ -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('')
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
"""
|
||||
}
|
||||
|
@ -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>"}, '<script>alert('foo')</script>'),
|
||||
|
||||
'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('"Safe" http://example.com?x=&y=')}, u'"Unsafe" <a href="http://example.com/x=&y=" rel="nofollow">http:...</a> "Safe" <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('"Safe" http://example.com?x=&y=')}, u'"Unsafe" <a href="http://example.com/x=&y=" rel="nofollow">http:...</a> "Safe" <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 & b")}, "3 3"),
|
||||
'filter-wordcount02': ('{{ a|wordcount }} {{ b|wordcount }}', {"a": "a & b", "b": mark_safe("a & b")}, "3 3"),
|
||||
|
1
tests/regressiontests/views/media/file.unknown
Normal file
1
tests/regressiontests/views/media/file.unknown
Normal file
@ -0,0 +1 @@
|
||||
An unknown file extension.
|
@ -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)
|
||||
|
||||
|
||||
|
||||
|
@ -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__":
|
||||
|
Loading…
x
Reference in New Issue
Block a user