mirror of
https://github.com/django/django.git
synced 2025-07-04 01:39:20 +00:00
newforms-admin: Merged from trunk up to [7729].
git-svn-id: http://code.djangoproject.com/svn/django/branches/newforms-admin@7730 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
c929440fcd
commit
420f19aa35
Binary file not shown.
@ -5,8 +5,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Django\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2008-05-26 10:35+0200\n"
|
||||
"PO-Revision-Date: 2008-05-14 11:15+0200\n"
|
||||
"POT-Creation-Date: 2008-06-20 12:36+0200\n"
|
||||
"PO-Revision-Date: 2008-06-20 12:48+0200\n"
|
||||
"Last-Translator: Django Catalan Group <django-cat@googlegroups.com>\n"
|
||||
"Language-Team: Catalan <ca@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -14,193 +14,201 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: conf/global_settings.py:43
|
||||
msgid "Arabic"
|
||||
msgstr "Arabic"
|
||||
|
||||
#: conf/global_settings.py:44
|
||||
msgid "Bengali"
|
||||
msgstr "Bengalí"
|
||||
msgid "Arabic"
|
||||
msgstr "aràbic"
|
||||
|
||||
#: conf/global_settings.py:45
|
||||
msgid "Bulgarian"
|
||||
msgstr "Búlgar"
|
||||
msgid "Bengali"
|
||||
msgstr "bengalí"
|
||||
|
||||
#: conf/global_settings.py:46
|
||||
msgid "Catalan"
|
||||
msgstr "Català"
|
||||
msgid "Bulgarian"
|
||||
msgstr "búlgar"
|
||||
|
||||
#: conf/global_settings.py:47
|
||||
msgid "Czech"
|
||||
msgstr "Txec"
|
||||
msgid "Catalan"
|
||||
msgstr "català"
|
||||
|
||||
#: conf/global_settings.py:48
|
||||
msgid "Welsh"
|
||||
msgstr "Galès"
|
||||
msgid "Czech"
|
||||
msgstr "txec"
|
||||
|
||||
#: conf/global_settings.py:49
|
||||
msgid "Danish"
|
||||
msgstr "Danès"
|
||||
msgid "Welsh"
|
||||
msgstr "galès"
|
||||
|
||||
#: conf/global_settings.py:50
|
||||
msgid "German"
|
||||
msgstr "Alemany"
|
||||
msgid "Danish"
|
||||
msgstr "danès"
|
||||
|
||||
#: conf/global_settings.py:51
|
||||
msgid "Greek"
|
||||
msgstr "Grec"
|
||||
msgid "German"
|
||||
msgstr "alemany"
|
||||
|
||||
#: conf/global_settings.py:52
|
||||
msgid "English"
|
||||
msgstr "Anglès"
|
||||
msgid "Greek"
|
||||
msgstr "grec"
|
||||
|
||||
#: conf/global_settings.py:53
|
||||
msgid "Spanish"
|
||||
msgstr "Espanyol"
|
||||
msgid "English"
|
||||
msgstr "anglès"
|
||||
|
||||
#: conf/global_settings.py:54
|
||||
msgid "Argentinean Spanish"
|
||||
msgstr "Castellà Argentí"
|
||||
msgid "Spanish"
|
||||
msgstr "espanyol"
|
||||
|
||||
#: conf/global_settings.py:55
|
||||
msgid "Basque"
|
||||
msgstr "Euskera"
|
||||
msgid "Estonian"
|
||||
msgstr "estonià"
|
||||
|
||||
#: conf/global_settings.py:56
|
||||
msgid "Persian"
|
||||
msgstr "Persa"
|
||||
msgid "Argentinean Spanish"
|
||||
msgstr "castellà argentí"
|
||||
|
||||
#: conf/global_settings.py:57
|
||||
msgid "Finnish"
|
||||
msgstr "Finlandès"
|
||||
msgid "Basque"
|
||||
msgstr "euskera"
|
||||
|
||||
#: conf/global_settings.py:58
|
||||
msgid "French"
|
||||
msgstr "Francès"
|
||||
msgid "Persian"
|
||||
msgstr "persa"
|
||||
|
||||
#: conf/global_settings.py:59
|
||||
msgid "Irish"
|
||||
msgstr "Irlandès"
|
||||
msgid "Finnish"
|
||||
msgstr "finlandès"
|
||||
|
||||
#: conf/global_settings.py:60
|
||||
msgid "Galician"
|
||||
msgstr "Gallec"
|
||||
msgid "French"
|
||||
msgstr "francès"
|
||||
|
||||
#: conf/global_settings.py:61
|
||||
msgid "Hungarian"
|
||||
msgstr "Húngar"
|
||||
msgid "Irish"
|
||||
msgstr "irlandès"
|
||||
|
||||
#: conf/global_settings.py:62
|
||||
msgid "Hebrew"
|
||||
msgstr "Hebreu"
|
||||
msgid "Galician"
|
||||
msgstr "gallec"
|
||||
|
||||
#: conf/global_settings.py:63
|
||||
msgid "Croatian"
|
||||
msgstr "Croat"
|
||||
msgid "Hungarian"
|
||||
msgstr "húngar"
|
||||
|
||||
#: conf/global_settings.py:64
|
||||
msgid "Icelandic"
|
||||
msgstr "Islandès"
|
||||
msgid "Hebrew"
|
||||
msgstr "hebreu"
|
||||
|
||||
#: conf/global_settings.py:65
|
||||
msgid "Italian"
|
||||
msgstr "Italià"
|
||||
msgid "Croatian"
|
||||
msgstr "croat"
|
||||
|
||||
#: conf/global_settings.py:66
|
||||
msgid "Japanese"
|
||||
msgstr "Japonès"
|
||||
msgid "Icelandic"
|
||||
msgstr "islandès"
|
||||
|
||||
#: conf/global_settings.py:67
|
||||
msgid "Georgian"
|
||||
msgstr "Georgià"
|
||||
msgid "Italian"
|
||||
msgstr "italià"
|
||||
|
||||
#: conf/global_settings.py:68
|
||||
msgid "Korean"
|
||||
msgstr "Coreà"
|
||||
msgid "Japanese"
|
||||
msgstr "japonès"
|
||||
|
||||
#: conf/global_settings.py:69
|
||||
msgid "Khmer"
|
||||
msgstr "Khmer"
|
||||
msgid "Georgian"
|
||||
msgstr "georgià"
|
||||
|
||||
#: conf/global_settings.py:70
|
||||
msgid "Kannada"
|
||||
msgstr "Canès"
|
||||
msgid "Korean"
|
||||
msgstr "coreà"
|
||||
|
||||
#: conf/global_settings.py:71
|
||||
msgid "Latvian"
|
||||
msgstr "Letó"
|
||||
msgid "khmer"
|
||||
msgstr "khmer"
|
||||
|
||||
#: conf/global_settings.py:72
|
||||
msgid "Macedonian"
|
||||
msgstr "Macedoni"
|
||||
msgid "Kannada"
|
||||
msgstr "canès"
|
||||
|
||||
#: conf/global_settings.py:73
|
||||
msgid "Dutch"
|
||||
msgstr "Holandès"
|
||||
msgid "Latvian"
|
||||
msgstr "letó"
|
||||
|
||||
#: conf/global_settings.py:74
|
||||
msgid "Norwegian"
|
||||
msgstr "Norueg"
|
||||
msgid "Lithuanian"
|
||||
msgstr "lituà"
|
||||
|
||||
#: conf/global_settings.py:75
|
||||
msgid "Polish"
|
||||
msgstr "Polac"
|
||||
msgid "Macedonian"
|
||||
msgstr "macedoni"
|
||||
|
||||
#: conf/global_settings.py:76
|
||||
msgid "Portugese"
|
||||
msgstr "Portuguès"
|
||||
msgid "Dutch"
|
||||
msgstr "holandès"
|
||||
|
||||
#: conf/global_settings.py:77
|
||||
msgid "Brazilian Portuguese"
|
||||
msgstr "Portuguès de Brasil"
|
||||
msgid "Norwegian"
|
||||
msgstr "norueg"
|
||||
|
||||
#: conf/global_settings.py:78
|
||||
msgid "Romanian"
|
||||
msgstr "Rumanès"
|
||||
msgid "Polish"
|
||||
msgstr "polac"
|
||||
|
||||
#: conf/global_settings.py:79
|
||||
msgid "Russian"
|
||||
msgstr "Rús"
|
||||
msgid "Portugese"
|
||||
msgstr "portuguès"
|
||||
|
||||
#: conf/global_settings.py:80
|
||||
msgid "Slovak"
|
||||
msgstr "Eslovac"
|
||||
msgid "Brazilian Portuguese"
|
||||
msgstr "portuguès de brasil"
|
||||
|
||||
#: conf/global_settings.py:81
|
||||
msgid "Slovenian"
|
||||
msgstr "Esloveni"
|
||||
msgid "Romanian"
|
||||
msgstr "rumanès"
|
||||
|
||||
#: conf/global_settings.py:82
|
||||
msgid "Serbian"
|
||||
msgstr "Serbi"
|
||||
msgid "Russian"
|
||||
msgstr "rús"
|
||||
|
||||
#: conf/global_settings.py:83
|
||||
msgid "Swedish"
|
||||
msgstr "Suec"
|
||||
msgid "Slovak"
|
||||
msgstr "eslovac"
|
||||
|
||||
#: conf/global_settings.py:84
|
||||
msgid "Tamil"
|
||||
msgstr "Tàmil"
|
||||
msgid "Slovenian"
|
||||
msgstr "esloveni"
|
||||
|
||||
#: conf/global_settings.py:85
|
||||
msgid "Telugu"
|
||||
msgstr "Telugu"
|
||||
msgid "Serbian"
|
||||
msgstr "serbi"
|
||||
|
||||
#: conf/global_settings.py:86
|
||||
msgid "Turkish"
|
||||
msgstr "Turc"
|
||||
msgid "Swedish"
|
||||
msgstr "suec"
|
||||
|
||||
#: conf/global_settings.py:87
|
||||
msgid "Ukrainian"
|
||||
msgstr "Ucranià"
|
||||
msgid "Tamil"
|
||||
msgstr "tàmil"
|
||||
|
||||
#: conf/global_settings.py:88
|
||||
msgid "Simplified Chinese"
|
||||
msgstr "Xinès simplificat"
|
||||
msgid "Telugu"
|
||||
msgstr "telugu"
|
||||
|
||||
#: conf/global_settings.py:89
|
||||
msgid "Turkish"
|
||||
msgstr "turc"
|
||||
|
||||
#: conf/global_settings.py:90
|
||||
msgid "Ukrainian"
|
||||
msgstr "ucranià"
|
||||
|
||||
#: conf/global_settings.py:91
|
||||
msgid "Simplified Chinese"
|
||||
msgstr "xinès simplificat"
|
||||
|
||||
#: conf/global_settings.py:92
|
||||
msgid "Traditional Chinese"
|
||||
msgstr "Xinès tradicional"
|
||||
msgstr "xinès tradicional"
|
||||
|
||||
#: contrib/admin/filterspecs.py:44
|
||||
#, python-format
|
||||
@ -1137,15 +1145,15 @@ msgstr "permisos"
|
||||
msgid "group"
|
||||
msgstr "grup"
|
||||
|
||||
#: contrib/auth/models.py:98 contrib/auth/models.py:141
|
||||
#: contrib/auth/models.py:98 contrib/auth/models.py:148
|
||||
msgid "groups"
|
||||
msgstr "grups"
|
||||
|
||||
#: contrib/auth/models.py:131
|
||||
#: contrib/auth/models.py:138
|
||||
msgid "username"
|
||||
msgstr "nom d'usuari"
|
||||
|
||||
#: contrib/auth/models.py:131
|
||||
#: contrib/auth/models.py:138
|
||||
msgid ""
|
||||
"Required. 30 characters or fewer. Alphanumeric characters only (letters, "
|
||||
"digits and underscores)."
|
||||
@ -1153,23 +1161,23 @@ msgstr ""
|
||||
"Obligatori. 30 o menys caràcters. Només caràcters alfanumèrics (lletres, "
|
||||
"dígits i el guió baix)."
|
||||
|
||||
#: contrib/auth/models.py:132
|
||||
#: contrib/auth/models.py:139
|
||||
msgid "first name"
|
||||
msgstr "nom propi"
|
||||
|
||||
#: contrib/auth/models.py:133
|
||||
#: contrib/auth/models.py:140
|
||||
msgid "last name"
|
||||
msgstr "cognoms"
|
||||
|
||||
#: contrib/auth/models.py:134
|
||||
#: contrib/auth/models.py:141
|
||||
msgid "e-mail address"
|
||||
msgstr "adreça de correu electrònic"
|
||||
|
||||
#: contrib/auth/models.py:135
|
||||
#: contrib/auth/models.py:142
|
||||
msgid "password"
|
||||
msgstr "contrasenya"
|
||||
|
||||
#: contrib/auth/models.py:135
|
||||
#: contrib/auth/models.py:142
|
||||
msgid ""
|
||||
"Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change "
|
||||
"password form</a>."
|
||||
@ -1177,19 +1185,19 @@ msgstr ""
|
||||
"Utilitzeu '[algo]$[salt]$[hexdigest]' o el <a href=\"password/\">formulari "
|
||||
"de canvi de contrasenya</a>."
|
||||
|
||||
#: contrib/auth/models.py:136
|
||||
#: contrib/auth/models.py:143
|
||||
msgid "staff status"
|
||||
msgstr "membre del personal"
|
||||
|
||||
#: contrib/auth/models.py:136
|
||||
#: contrib/auth/models.py:143
|
||||
msgid "Designates whether the user can log into this admin site."
|
||||
msgstr "Indica si l'usuari pot entrar en el lloc administratiu."
|
||||
|
||||
#: contrib/auth/models.py:137
|
||||
#: contrib/auth/models.py:144
|
||||
msgid "active"
|
||||
msgstr "actiu"
|
||||
|
||||
#: contrib/auth/models.py:137
|
||||
#: contrib/auth/models.py:144
|
||||
msgid ""
|
||||
"Designates whether this user should be treated as active. Unselect this "
|
||||
"instead of deleting accounts."
|
||||
@ -1197,11 +1205,11 @@ msgstr ""
|
||||
"Designa si aquest usuari ha de ser tractat com a actiu. Deseleccioneu-ho "
|
||||
"enlloc d'esborrar comptes d'usuari."
|
||||
|
||||
#: contrib/auth/models.py:138
|
||||
#: contrib/auth/models.py:145
|
||||
msgid "superuser status"
|
||||
msgstr "estat de superusuari"
|
||||
|
||||
#: contrib/auth/models.py:138
|
||||
#: contrib/auth/models.py:145
|
||||
msgid ""
|
||||
"Designates that this user has all permissions without explicitly assigning "
|
||||
"them."
|
||||
@ -1209,15 +1217,15 @@ msgstr ""
|
||||
"Designa que aquest usuari té tots els permissos sense assignar-los "
|
||||
"explícitament."
|
||||
|
||||
#: contrib/auth/models.py:139
|
||||
#: contrib/auth/models.py:146
|
||||
msgid "last login"
|
||||
msgstr "últim inici de sessió"
|
||||
|
||||
#: contrib/auth/models.py:140
|
||||
#: contrib/auth/models.py:147
|
||||
msgid "date joined"
|
||||
msgstr "data de creació"
|
||||
|
||||
#: contrib/auth/models.py:142
|
||||
#: contrib/auth/models.py:149
|
||||
msgid ""
|
||||
"In addition to the permissions manually assigned, this user will also get "
|
||||
"all permissions granted to each group he/she is in."
|
||||
@ -1225,39 +1233,39 @@ msgstr ""
|
||||
"Junt amb els permissos asignats manualment, aquest usuari tindrà, també, els "
|
||||
"permissos dels grups dels que sigui membre."
|
||||
|
||||
#: contrib/auth/models.py:143
|
||||
#: contrib/auth/models.py:150
|
||||
msgid "user permissions"
|
||||
msgstr "permissos de l'usuari"
|
||||
|
||||
#: contrib/auth/models.py:147
|
||||
#: contrib/auth/models.py:154
|
||||
msgid "user"
|
||||
msgstr "usuari"
|
||||
|
||||
#: contrib/auth/models.py:148
|
||||
#: contrib/auth/models.py:155
|
||||
msgid "users"
|
||||
msgstr "usuaris"
|
||||
|
||||
#: contrib/auth/models.py:154
|
||||
#: contrib/auth/models.py:161
|
||||
msgid "Personal info"
|
||||
msgstr "Informació personal"
|
||||
|
||||
#: contrib/auth/models.py:155
|
||||
#: contrib/auth/models.py:162
|
||||
msgid "Permissions"
|
||||
msgstr "permisos"
|
||||
|
||||
#: contrib/auth/models.py:156
|
||||
#: contrib/auth/models.py:163
|
||||
msgid "Important dates"
|
||||
msgstr "Dates importants"
|
||||
|
||||
#: contrib/auth/models.py:157
|
||||
#: contrib/auth/models.py:164
|
||||
msgid "Groups"
|
||||
msgstr "Grups"
|
||||
|
||||
#: contrib/auth/models.py:316
|
||||
#: contrib/auth/models.py:323
|
||||
msgid "message"
|
||||
msgstr "missatge"
|
||||
|
||||
#: contrib/auth/views.py:47
|
||||
#: contrib/auth/views.py:48
|
||||
msgid "Logged out"
|
||||
msgstr "Sessió finalitzada"
|
||||
|
||||
@ -3897,12 +3905,12 @@ msgstr ""
|
||||
msgid "%(object)s with this %(type)s already exists for the given %(field)s."
|
||||
msgstr "Ja existeix un %(object)s del tipus %(type)s amb aquest %(field)s."
|
||||
|
||||
#: db/models/fields/__init__.py:54
|
||||
#: db/models/fields/__init__.py:51
|
||||
#, python-format
|
||||
msgid "%(optname)s with this %(fieldname)s already exists."
|
||||
msgstr "Ja existeix %(optname)s amb aquest %(fieldname)s."
|
||||
|
||||
#: db/models/fields/__init__.py:179 db/models/fields/__init__.py:348
|
||||
#: db/models/fields/__init__.py:176 db/models/fields/__init__.py:348
|
||||
#: db/models/fields/__init__.py:780 db/models/fields/__init__.py:791
|
||||
#: newforms/fields.py:46 oldforms/__init__.py:374
|
||||
msgid "This field is required."
|
||||
@ -3937,18 +3945,18 @@ msgstr "Aquest valor ha de ser None (Cap), True (Veritat) o False (Fals)"
|
||||
msgid "Please enter a valid %s."
|
||||
msgstr "Si us plau, introduïu un %s vàlid."
|
||||
|
||||
#: db/models/fields/related.py:721
|
||||
#: db/models/fields/related.py:746
|
||||
msgid "Separate multiple IDs with commas."
|
||||
msgstr "Separi múltiples IDs amb comes."
|
||||
|
||||
#: db/models/fields/related.py:723
|
||||
#: db/models/fields/related.py:748
|
||||
msgid ""
|
||||
"Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
|
||||
msgstr ""
|
||||
"Premeu la tecla \"Control\" -o \"Command\" en un Mac- per seleccionar més "
|
||||
"d'un valor."
|
||||
|
||||
#: db/models/fields/related.py:770
|
||||
#: db/models/fields/related.py:795
|
||||
#, python-format
|
||||
msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid."
|
||||
msgid_plural ""
|
||||
@ -4007,11 +4015,11 @@ msgstr "Assegureu-vos de que no hi ha més de %s decimals."
|
||||
msgid "Ensure that there are no more than %s digits before the decimal point."
|
||||
msgstr "Assegureu-vos de que no hi ha més de %s dígits decimals."
|
||||
|
||||
#: newforms/fields.py:263 newforms/fields.py:751
|
||||
#: newforms/fields.py:263 newforms/fields.py:750
|
||||
msgid "Enter a valid date."
|
||||
msgstr "Introduïu una data vàlida."
|
||||
|
||||
#: newforms/fields.py:296 newforms/fields.py:752
|
||||
#: newforms/fields.py:296 newforms/fields.py:751
|
||||
msgid "Enter a valid time."
|
||||
msgstr "Introduïu una hora vàlida."
|
||||
|
||||
@ -4035,25 +4043,25 @@ msgstr "Introduïu una URL vàlida."
|
||||
msgid "This URL appears to be a broken link."
|
||||
msgstr "Aquesta URL sembla ser un enllaç trencat."
|
||||
|
||||
#: newforms/fields.py:560 newforms/models.py:299
|
||||
#: newforms/fields.py:559 newforms/models.py:305
|
||||
msgid "Select a valid choice. That choice is not one of the available choices."
|
||||
msgstr ""
|
||||
"Escolli una opció vàlida; Aquesta opció no és una de les opcions disponibles."
|
||||
|
||||
#: newforms/fields.py:599
|
||||
#: newforms/fields.py:598
|
||||
#, python-format
|
||||
msgid "Select a valid choice. %(value)s is not one of the available choices."
|
||||
msgstr "Esculliu 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:371
|
||||
#: newforms/fields.py:599 newforms/fields.py:661 newforms/models.py:372
|
||||
msgid "Enter a list of values."
|
||||
msgstr "Introduïu una llista de valors."
|
||||
|
||||
#: newforms/fields.py:780
|
||||
#: newforms/fields.py:779
|
||||
msgid "Enter a valid IPv4 address."
|
||||
msgstr "Introduïu una adreça IPv4 vàlida."
|
||||
|
||||
#: newforms/models.py:372
|
||||
#: newforms/models.py:373
|
||||
#, python-format
|
||||
msgid "Select a valid choice. %s is not one of the available choices."
|
||||
msgstr "Escolliu una opció vàlida; %s' no és una de les opcions vàlides."
|
||||
@ -4194,51 +4202,51 @@ msgstr "Dg"
|
||||
|
||||
#: utils/dates.py:18
|
||||
msgid "January"
|
||||
msgstr "Gener"
|
||||
msgstr "gener"
|
||||
|
||||
#: utils/dates.py:18
|
||||
msgid "February"
|
||||
msgstr "Febrer"
|
||||
msgstr "febrer"
|
||||
|
||||
#: utils/dates.py:18 utils/dates.py:31
|
||||
msgid "March"
|
||||
msgstr "Març"
|
||||
msgstr "març"
|
||||
|
||||
#: utils/dates.py:18 utils/dates.py:31
|
||||
msgid "April"
|
||||
msgstr "Abril"
|
||||
msgstr "abril"
|
||||
|
||||
#: utils/dates.py:18 utils/dates.py:31
|
||||
msgid "May"
|
||||
msgstr "Maig"
|
||||
msgstr "maig"
|
||||
|
||||
#: utils/dates.py:18 utils/dates.py:31
|
||||
msgid "June"
|
||||
msgstr "Juny"
|
||||
msgstr "juny"
|
||||
|
||||
#: utils/dates.py:19 utils/dates.py:31
|
||||
msgid "July"
|
||||
msgstr "Juliol"
|
||||
msgstr "juliol"
|
||||
|
||||
#: utils/dates.py:19
|
||||
msgid "August"
|
||||
msgstr "Agost"
|
||||
msgstr "agost"
|
||||
|
||||
#: utils/dates.py:19
|
||||
msgid "September"
|
||||
msgstr "Setembre"
|
||||
msgstr "setembre"
|
||||
|
||||
#: utils/dates.py:19
|
||||
msgid "October"
|
||||
msgstr "Octubre"
|
||||
msgstr "octubre"
|
||||
|
||||
#: utils/dates.py:19
|
||||
msgid "November"
|
||||
msgstr "Novembre"
|
||||
msgstr "novembre"
|
||||
|
||||
#: utils/dates.py:20
|
||||
msgid "December"
|
||||
msgstr "Desembre"
|
||||
msgstr "desembre"
|
||||
|
||||
#: utils/dates.py:23
|
||||
msgid "jan"
|
||||
@ -4290,31 +4298,31 @@ msgstr "des"
|
||||
|
||||
#: utils/dates.py:31
|
||||
msgid "Jan."
|
||||
msgstr "Gen."
|
||||
msgstr "gen."
|
||||
|
||||
#: utils/dates.py:31
|
||||
msgid "Feb."
|
||||
msgstr "Feb."
|
||||
msgstr "feb."
|
||||
|
||||
#: utils/dates.py:32
|
||||
msgid "Aug."
|
||||
msgstr "Ago."
|
||||
msgstr "ago."
|
||||
|
||||
#: utils/dates.py:32
|
||||
msgid "Sept."
|
||||
msgstr "Set."
|
||||
msgstr "set."
|
||||
|
||||
#: utils/dates.py:32
|
||||
msgid "Oct."
|
||||
msgstr "Oct."
|
||||
msgstr "oct."
|
||||
|
||||
#: utils/dates.py:32
|
||||
msgid "Nov."
|
||||
msgstr "Nov."
|
||||
msgstr "nov."
|
||||
|
||||
#: utils/dates.py:32
|
||||
msgid "Dec."
|
||||
msgstr "Des."
|
||||
msgstr "des."
|
||||
|
||||
#: utils/text.py:127
|
||||
msgid "or"
|
||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -7,12 +7,13 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Django\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2005-12-09 11:51+0100\n"
|
||||
"PO-Revision-Date: 2005-12-04 13:21+0100\n"
|
||||
"Last-Translator: Dirk Eschler <dirk.eschler@gmx.net>\n"
|
||||
"POT-Creation-Date: 2008-06-23 20:52+0200\n"
|
||||
"PO-Revision-Date: 2008-06-23 21:02+0100\n"
|
||||
"Last-Translator: Jannis Leidel <jannis@leidel.info>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language-Team: \n"
|
||||
|
||||
#: contrib/admin/media/js/SelectFilter2.js:33
|
||||
#, perl-format
|
||||
@ -38,82 +39,78 @@ msgstr "Ausgewählte %s"
|
||||
|
||||
#: contrib/admin/media/js/SelectFilter2.js:54
|
||||
msgid "Select your choice(s) and click "
|
||||
msgstr "Gewünschte Auswahl treffen und "
|
||||
msgstr "Auswahl treffen und Klick auf"
|
||||
|
||||
#: contrib/admin/media/js/SelectFilter2.js:59
|
||||
msgid "Clear all"
|
||||
msgstr "Alles abwählen"
|
||||
|
||||
#: contrib/admin/media/js/dateparse.js:26
|
||||
#: contrib/admin/media/js/calendar.js:24
|
||||
msgid ""
|
||||
"January February March April May June July August September October November "
|
||||
"December"
|
||||
msgstr ""
|
||||
"Januar Februar März April Mai Juni Juli August September Oktober November "
|
||||
"Dezember"
|
||||
|
||||
#: contrib/admin/media/js/dateparse.js:27
|
||||
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
|
||||
msgstr "Sonntag Montag Dienstag Mittwoch Donnerstag Freitag Samstag"
|
||||
#: contrib/admin/media/js/dateparse.js:32
|
||||
msgid "January February March April May June July August September October November December"
|
||||
msgstr "Januar Februar März April Mai Juni Juli August September Oktober November Dezember"
|
||||
|
||||
#: contrib/admin/media/js/calendar.js:25
|
||||
msgid "S M T W T F S"
|
||||
msgstr "S M D M D F S"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80
|
||||
msgid "Now"
|
||||
msgstr "Jetzt"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:48
|
||||
msgid "Clock"
|
||||
msgstr "Uhr"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:77
|
||||
msgid "Choose a time"
|
||||
msgstr "Uhrzeit"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
|
||||
msgid "Midnight"
|
||||
msgstr "Mitternacht"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
|
||||
msgid "6 a.m."
|
||||
msgstr "6 Uhr"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
|
||||
msgid "Noon"
|
||||
msgstr "Mittag"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:87
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:168
|
||||
msgid "Cancel"
|
||||
msgstr "Abbrechen"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:111
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:162
|
||||
msgid "Today"
|
||||
msgstr "Heute"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:114
|
||||
msgid "Calendar"
|
||||
msgstr "Kalender"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:160
|
||||
msgid "Yesterday"
|
||||
msgstr "Gestern"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164
|
||||
msgid "Tomorrow"
|
||||
msgstr "Morgen"
|
||||
#: contrib/admin/media/js/dateparse.js:33
|
||||
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
|
||||
msgstr "Sonntag Montag Dienstag Mittwoch Donnerstag Freitag Samstag"
|
||||
|
||||
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:34
|
||||
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:72
|
||||
msgid "Show"
|
||||
msgstr "Anzeigen"
|
||||
msgstr "Einblenden"
|
||||
|
||||
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:63
|
||||
msgid "Hide"
|
||||
msgstr "Verbergen"
|
||||
msgstr "Ausblenden"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:47
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
|
||||
msgid "Now"
|
||||
msgstr "Jetzt"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:51
|
||||
msgid "Clock"
|
||||
msgstr "Uhr"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:78
|
||||
msgid "Choose a time"
|
||||
msgstr "Uhrzeit"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
|
||||
msgid "Midnight"
|
||||
msgstr "Mitternacht"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
|
||||
msgid "6 a.m."
|
||||
msgstr "6 Uhr"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:84
|
||||
msgid "Noon"
|
||||
msgstr "Mittag"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:88
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
|
||||
msgid "Cancel"
|
||||
msgstr "Abbrechen"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:128
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:177
|
||||
msgid "Today"
|
||||
msgstr "Heute"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:132
|
||||
msgid "Calendar"
|
||||
msgstr "Kalender"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:175
|
||||
msgid "Yesterday"
|
||||
msgstr "Gestern"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
|
||||
msgid "Tomorrow"
|
||||
msgstr "Morgen"
|
||||
|
||||
|
@ -5,14 +5,15 @@ import random
|
||||
import sys
|
||||
import time
|
||||
from datetime import datetime, timedelta
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import SuspiciousOperation
|
||||
|
||||
try:
|
||||
import cPickle as pickle
|
||||
except ImportError:
|
||||
import pickle
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import SuspiciousOperation
|
||||
|
||||
|
||||
class SessionBase(object):
|
||||
"""
|
||||
Base class for all Session classes.
|
||||
@ -169,8 +170,8 @@ class SessionBase(object):
|
||||
|
||||
def set_expiry(self, value):
|
||||
"""
|
||||
Sets a custom expiration for the session. ``value`` can be an integer, a
|
||||
Python ``datetime`` or ``timedelta`` object or ``None``.
|
||||
Sets a custom expiration for the session. ``value`` can be an integer,
|
||||
a Python ``datetime`` or ``timedelta`` object or ``None``.
|
||||
|
||||
If ``value`` is an integer, the session will expire after that many
|
||||
seconds of inactivity. If set to ``0`` then the session will expire on
|
||||
|
@ -2,6 +2,7 @@ from django.conf import settings
|
||||
from django.contrib.sessions.backends.base import SessionBase
|
||||
from django.core.cache import cache
|
||||
|
||||
|
||||
class SessionStore(SessionBase):
|
||||
"""
|
||||
A cache-based session store.
|
||||
@ -23,4 +24,4 @@ class SessionStore(SessionBase):
|
||||
return False
|
||||
|
||||
def delete(self, session_key):
|
||||
self._cache.delete(session_key)
|
||||
self._cache.delete(session_key)
|
||||
|
@ -1,12 +1,14 @@
|
||||
import datetime
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.sessions.models import Session
|
||||
from django.contrib.sessions.backends.base import SessionBase
|
||||
from django.core.exceptions import SuspiciousOperation
|
||||
import datetime
|
||||
|
||||
|
||||
class SessionStore(SessionBase):
|
||||
"""
|
||||
Implements database session store
|
||||
Implements database session store.
|
||||
"""
|
||||
def __init__(self, session_key=None):
|
||||
super(SessionStore, self).__init__(session_key)
|
||||
|
@ -1,9 +1,11 @@
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.sessions.backends.base import SessionBase
|
||||
from django.core.exceptions import SuspiciousOperation, ImproperlyConfigured
|
||||
|
||||
|
||||
class SessionStore(SessionBase):
|
||||
"""
|
||||
Implements a file based session store.
|
||||
@ -15,10 +17,10 @@ class SessionStore(SessionBase):
|
||||
|
||||
# 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)
|
||||
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)
|
||||
@ -31,9 +33,11 @@ class SessionStore(SessionBase):
|
||||
session_key = self.session_key
|
||||
|
||||
# Make sure we're not vulnerable to directory traversal. Session keys
|
||||
# should always be md5s, so they should never contain directory components.
|
||||
# should always be md5s, so they should never contain directory
|
||||
# components.
|
||||
if os.path.sep in session_key:
|
||||
raise SuspiciousOperation("Invalid characters (directory components) in session key")
|
||||
raise SuspiciousOperation(
|
||||
"Invalid characters (directory components) in session key")
|
||||
|
||||
return os.path.join(self.storage_path, self.file_prefix + session_key)
|
||||
|
||||
|
@ -7,6 +7,7 @@ from django.utils.http import cookie_date
|
||||
TEST_COOKIE_NAME = 'testcookie'
|
||||
TEST_COOKIE_VALUE = 'worked'
|
||||
|
||||
|
||||
class SessionMiddleware(object):
|
||||
|
||||
def process_request(self, request):
|
||||
@ -40,5 +41,4 @@ class SessionMiddleware(object):
|
||||
expires=expires, domain=settings.SESSION_COOKIE_DOMAIN,
|
||||
path=settings.SESSION_COOKIE_PATH,
|
||||
secure=settings.SESSION_COOKIE_SECURE or None)
|
||||
|
||||
return response
|
||||
|
@ -6,9 +6,12 @@ from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
class SessionManager(models.Manager):
|
||||
def encode(self, session_dict):
|
||||
"Returns the given session dictionary pickled and encoded as a string."
|
||||
"""
|
||||
Returns the given session dictionary pickled and encoded as a string.
|
||||
"""
|
||||
pickled = pickle.dumps(session_dict)
|
||||
pickled_md5 = md5.new(pickled + settings.SECRET_KEY).hexdigest()
|
||||
return base64.encodestring(pickled + pickled_md5)
|
||||
@ -21,6 +24,7 @@ class SessionManager(models.Manager):
|
||||
s.delete() # Clear sessions with no data.
|
||||
return s
|
||||
|
||||
|
||||
class Session(models.Model):
|
||||
"""
|
||||
Django provides full support for anonymous sessions. The session
|
||||
@ -38,7 +42,8 @@ class Session(models.Model):
|
||||
the sessions documentation that is shipped with Django (also available
|
||||
on the Django website).
|
||||
"""
|
||||
session_key = models.CharField(_('session key'), max_length=40, primary_key=True)
|
||||
session_key = models.CharField(_('session key'), max_length=40,
|
||||
primary_key=True)
|
||||
session_data = models.TextField(_('session data'))
|
||||
expire_date = models.DateTimeField(_('expire date'))
|
||||
objects = SessionManager()
|
||||
|
@ -13,5 +13,6 @@ def create_default_site(app, created_models, verbosity):
|
||||
print "Creating example.com Site object"
|
||||
s = Site(domain="example.com", name="example.com")
|
||||
s.save()
|
||||
Site.objects.clear_cache()
|
||||
|
||||
dispatcher.connect(create_default_site, sender=site_app, signal=signals.post_syncdb)
|
||||
|
@ -41,7 +41,15 @@ class Site(models.Model):
|
||||
|
||||
def __unicode__(self):
|
||||
return self.domain
|
||||
|
||||
|
||||
def delete(self):
|
||||
pk = self.pk
|
||||
super(Site, self).delete()
|
||||
try:
|
||||
del(SITE_CACHE[pk])
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
# Register the admin options for these models.
|
||||
# TODO: Maybe this should live in a separate module admin.py, but how would we
|
||||
# ensure that module was loaded?
|
||||
|
13
django/contrib/sites/tests.py
Normal file
13
django/contrib/sites/tests.py
Normal file
@ -0,0 +1,13 @@
|
||||
"""
|
||||
>>> # Make sure that get_current() does not return a deleted Site object.
|
||||
>>> from django.contrib.sites.models import Site
|
||||
>>> s = Site.objects.get_current()
|
||||
>>> s
|
||||
<Site: example.com>
|
||||
|
||||
>>> s.delete()
|
||||
>>> Site.objects.get_current()
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
DoesNotExist: Site matching query does not exist.
|
||||
"""
|
@ -10,7 +10,7 @@ from django.core import validators
|
||||
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned, FieldError
|
||||
from django.db.models.fields import AutoField, ImageField, FieldDoesNotExist
|
||||
from django.db.models.fields.related import OneToOneRel, ManyToOneRel, OneToOneField
|
||||
from django.db.models.query import delete_objects, Q
|
||||
from django.db.models.query import delete_objects, Q, CollectedObjects
|
||||
from django.db.models.options import Options
|
||||
from django.db import connection, transaction
|
||||
from django.db.models import signals
|
||||
@ -365,17 +365,16 @@ class Model(object):
|
||||
error_dict[f.name] = errors
|
||||
return error_dict
|
||||
|
||||
def _collect_sub_objects(self, seen_objs):
|
||||
def _collect_sub_objects(self, seen_objs, parent=None, nullable=False):
|
||||
"""
|
||||
Recursively populates seen_objs with all objects related to this object.
|
||||
When done, seen_objs will be in the format:
|
||||
{model_class: {pk_val: obj, pk_val: obj, ...},
|
||||
model_class: {pk_val: obj, pk_val: obj, ...}, ...}
|
||||
When done, seen_objs.items() will be in the format:
|
||||
[(model_class, {pk_val: obj, pk_val: obj, ...}),
|
||||
(model_class, {pk_val: obj, pk_val: obj, ...}),...]
|
||||
"""
|
||||
pk_val = self._get_pk_val()
|
||||
if pk_val in seen_objs.setdefault(self.__class__, {}):
|
||||
if seen_objs.add(self.__class__, pk_val, self, parent, nullable):
|
||||
return
|
||||
seen_objs.setdefault(self.__class__, {})[pk_val] = self
|
||||
|
||||
for related in self._meta.get_all_related_objects():
|
||||
rel_opts_name = related.get_accessor_name()
|
||||
@ -385,16 +384,16 @@ class Model(object):
|
||||
except ObjectDoesNotExist:
|
||||
pass
|
||||
else:
|
||||
sub_obj._collect_sub_objects(seen_objs)
|
||||
sub_obj._collect_sub_objects(seen_objs, self.__class__, related.field.null)
|
||||
else:
|
||||
for sub_obj in getattr(self, rel_opts_name).all():
|
||||
sub_obj._collect_sub_objects(seen_objs)
|
||||
sub_obj._collect_sub_objects(seen_objs, self.__class__, related.field.null)
|
||||
|
||||
def delete(self):
|
||||
assert self._get_pk_val() is not None, "%s object can't be deleted because its %s attribute is set to None." % (self._meta.object_name, self._meta.pk.attname)
|
||||
|
||||
# Find all the objects than need to be deleted
|
||||
seen_objs = SortedDict()
|
||||
seen_objs = CollectedObjects()
|
||||
self._collect_sub_objects(seen_objs)
|
||||
|
||||
# Actually delete the objects
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.utils.datastructures import SortedDict
|
||||
|
||||
import sys
|
||||
import os
|
||||
import threading
|
||||
@ -18,10 +20,10 @@ class AppCache(object):
|
||||
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66531.
|
||||
__shared_state = dict(
|
||||
# Keys of app_store are the model modules for each application.
|
||||
app_store = {},
|
||||
app_store = SortedDict(),
|
||||
|
||||
# Mapping of app_labels to a dictionary of model names to model code.
|
||||
app_models = {},
|
||||
app_models = SortedDict(),
|
||||
|
||||
# Mapping of app_labels to errors raised when trying to import the app.
|
||||
app_errors = {},
|
||||
@ -133,7 +135,7 @@ class AppCache(object):
|
||||
"""
|
||||
self._populate()
|
||||
if app_mod:
|
||||
return self.app_models.get(app_mod.__name__.split('.')[-2], {}).values()
|
||||
return self.app_models.get(app_mod.__name__.split('.')[-2], SortedDict()).values()
|
||||
else:
|
||||
model_list = []
|
||||
for app_entry in self.app_models.itervalues():
|
||||
@ -149,7 +151,7 @@ class AppCache(object):
|
||||
"""
|
||||
if seed_cache:
|
||||
self._populate()
|
||||
return self.app_models.get(app_label, {}).get(model_name.lower())
|
||||
return self.app_models.get(app_label, SortedDict()).get(model_name.lower())
|
||||
|
||||
def register_models(self, app_label, *models):
|
||||
"""
|
||||
@ -159,7 +161,7 @@ class AppCache(object):
|
||||
# Store as 'name: model' pair in a dictionary
|
||||
# in the app_models dictionary
|
||||
model_name = model._meta.object_name.lower()
|
||||
model_dict = self.app_models.setdefault(app_label, {})
|
||||
model_dict = self.app_models.setdefault(app_label, SortedDict())
|
||||
if model_name in model_dict:
|
||||
# The same model may be imported via different paths (e.g.
|
||||
# appname.models and project.appname.models). We use the source
|
||||
|
@ -16,6 +16,92 @@ ITER_CHUNK_SIZE = CHUNK_SIZE
|
||||
# Pull into this namespace for backwards compatibility
|
||||
EmptyResultSet = sql.EmptyResultSet
|
||||
|
||||
class CyclicDependency(Exception):
|
||||
pass
|
||||
|
||||
class CollectedObjects(object):
|
||||
"""
|
||||
A container that stores keys and lists of values along with
|
||||
remembering the parent objects for all the keys.
|
||||
|
||||
This is used for the database object deletion routines so that we
|
||||
can calculate the 'leaf' objects which should be deleted first.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.data = {}
|
||||
self.children = {}
|
||||
|
||||
def add(self, model, pk, obj, parent_model, nullable=False):
|
||||
"""
|
||||
Adds an item.
|
||||
model is the class of the object being added,
|
||||
pk is the primary key, obj is the object itself,
|
||||
parent_model is the model of the parent object
|
||||
that this object was reached through, nullable should
|
||||
be True if this relation is nullable.
|
||||
|
||||
If the item already existed in the structure,
|
||||
returns true, otherwise false.
|
||||
"""
|
||||
d = self.data.setdefault(model, SortedDict())
|
||||
retval = pk in d
|
||||
d[pk] = obj
|
||||
# Nullable relationships can be ignored -- they
|
||||
# are nulled out before deleting, and therefore
|
||||
# do not affect the order in which objects have
|
||||
# to be deleted.
|
||||
if parent_model is not None and not nullable:
|
||||
self.children.setdefault(parent_model, []).append(model)
|
||||
|
||||
return retval
|
||||
|
||||
def __contains__(self, key):
|
||||
return self.data.__contains__(key)
|
||||
|
||||
def __getitem__(self, key):
|
||||
return self.data[key]
|
||||
|
||||
def __nonzero__(self):
|
||||
return bool(self.data)
|
||||
|
||||
def iteritems(self):
|
||||
for k in self.ordered_keys():
|
||||
yield k, self[k]
|
||||
|
||||
def items(self):
|
||||
return list(self.iteritems())
|
||||
|
||||
def keys(self):
|
||||
return self.ordered_keys()
|
||||
|
||||
def ordered_keys(self):
|
||||
"""
|
||||
Returns the models in the order that they should be
|
||||
dealth with i.e. models with no dependencies first.
|
||||
"""
|
||||
dealt_with = SortedDict()
|
||||
# Start with items that have no children
|
||||
models = self.data.keys()
|
||||
while len(dealt_with) < len(models):
|
||||
found = False
|
||||
for model in models:
|
||||
children = self.children.setdefault(model, [])
|
||||
if len([c for c in children if c not in dealt_with]) == 0:
|
||||
dealt_with[model] = None
|
||||
found = True
|
||||
if not found:
|
||||
raise CyclicDependency("There is a cyclic dependency of items to be processed.")
|
||||
|
||||
return dealt_with.keys()
|
||||
|
||||
def unordered_keys(self):
|
||||
"""
|
||||
Fallback for the case where is a cyclic dependency but we
|
||||
don't care.
|
||||
"""
|
||||
return self.data.keys()
|
||||
|
||||
class QuerySet(object):
|
||||
"Represents a lazy database lookup for a set of objects"
|
||||
def __init__(self, model=None, query=None):
|
||||
@ -275,7 +361,7 @@ class QuerySet(object):
|
||||
while 1:
|
||||
# Collect all the objects to be deleted in this chunk, and all the
|
||||
# objects that are related to the objects that are to be deleted.
|
||||
seen_objs = SortedDict()
|
||||
seen_objs = CollectedObjects()
|
||||
for object in del_query[:CHUNK_SIZE]:
|
||||
object._collect_sub_objects(seen_objs)
|
||||
|
||||
@ -682,19 +768,27 @@ def delete_objects(seen_objs):
|
||||
Iterate through a list of seen classes, and remove any instances that are
|
||||
referred to.
|
||||
"""
|
||||
ordered_classes = seen_objs.keys()
|
||||
ordered_classes.reverse()
|
||||
try:
|
||||
ordered_classes = seen_objs.keys()
|
||||
except CyclicDependency:
|
||||
# if there is a cyclic dependency, we cannot in general delete
|
||||
# the objects. However, if an appropriate transaction is set
|
||||
# up, or if the database is lax enough, it will succeed.
|
||||
# So for now, we go ahead and try anway.
|
||||
ordered_classes = seen_objs.unordered_keys()
|
||||
|
||||
obj_pairs = {}
|
||||
for cls in ordered_classes:
|
||||
seen_objs[cls] = seen_objs[cls].items()
|
||||
seen_objs[cls].sort()
|
||||
items = seen_objs[cls].items()
|
||||
items.sort()
|
||||
obj_pairs[cls] = items
|
||||
|
||||
# Pre notify all instances to be deleted
|
||||
for pk_val, instance in seen_objs[cls]:
|
||||
for pk_val, instance in items:
|
||||
dispatcher.send(signal=signals.pre_delete, sender=cls,
|
||||
instance=instance)
|
||||
|
||||
pk_list = [pk for pk,instance in seen_objs[cls]]
|
||||
pk_list = [pk for pk,instance in items]
|
||||
del_query = sql.DeleteQuery(cls, connection)
|
||||
del_query.delete_batch_related(pk_list)
|
||||
|
||||
@ -705,15 +799,17 @@ def delete_objects(seen_objs):
|
||||
|
||||
# Now delete the actual data
|
||||
for cls in ordered_classes:
|
||||
seen_objs[cls].reverse()
|
||||
pk_list = [pk for pk,instance in seen_objs[cls]]
|
||||
items = obj_pairs[cls]
|
||||
items.reverse()
|
||||
|
||||
pk_list = [pk for pk,instance in items]
|
||||
del_query = sql.DeleteQuery(cls, connection)
|
||||
del_query.delete_batch(pk_list)
|
||||
|
||||
# Last cleanup; set NULLs where there once was a reference to the
|
||||
# object, NULL the primary key of the found objects, and perform
|
||||
# post-notification.
|
||||
for pk_val, instance in seen_objs[cls]:
|
||||
for pk_val, instance in items:
|
||||
for field in cls._meta.fields:
|
||||
if field.rel and field.null and field.rel.to in seen_objs:
|
||||
setattr(instance, field.attname, None)
|
||||
|
@ -483,11 +483,17 @@ class ModelChoiceIterator(object):
|
||||
def __iter__(self):
|
||||
if self.field.empty_label is not None:
|
||||
yield (u"", self.field.empty_label)
|
||||
for obj in self.queryset:
|
||||
yield (obj.pk, self.field.label_from_instance(obj))
|
||||
# Clear the QuerySet cache if required.
|
||||
if not self.field.cache_choices:
|
||||
self.queryset._result_cache = None
|
||||
if self.field.cache_choices:
|
||||
if self.field.choice_cache is None:
|
||||
self.field.choice_cache = [
|
||||
(obj.pk, self.field.label_from_instance(obj))
|
||||
for obj in self.queryset.all()
|
||||
]
|
||||
for choice in self.field.choice_cache:
|
||||
yield choice
|
||||
else:
|
||||
for obj in self.queryset.all():
|
||||
yield (obj.pk, self.field.label_from_instance(obj))
|
||||
|
||||
class ModelChoiceField(ChoiceField):
|
||||
"""A ChoiceField whose choices are a model QuerySet."""
|
||||
@ -509,6 +515,7 @@ class ModelChoiceField(ChoiceField):
|
||||
Field.__init__(self, required, widget, label, initial, help_text,
|
||||
*args, **kwargs)
|
||||
self.queryset = queryset
|
||||
self.choice_cache = None
|
||||
|
||||
def _get_queryset(self):
|
||||
return self._queryset
|
||||
|
@ -702,13 +702,8 @@ Django tarball. It's our policy to make sure all tests pass at all times.
|
||||
The tests cover:
|
||||
|
||||
* Models and the database API (``tests/modeltests/``).
|
||||
* The cache system (``tests/regressiontests/cache.py``).
|
||||
* The ``django.utils.dateformat`` module (``tests/regressiontests/dateformat/``).
|
||||
* Database typecasts (``tests/regressiontests/db_typecasts/``).
|
||||
* The template system (``tests/regressiontests/templates/`` and
|
||||
``tests/regressiontests/defaultfilters/``).
|
||||
* ``QueryDict`` objects (``tests/regressiontests/httpwrappers/``).
|
||||
* Markup template tags (``tests/regressiontests/markup/``).
|
||||
* Everything else in core Django code (``tests/regressiontests``)
|
||||
* Contrib apps (``django/contrib/<contribapp>/tests``, see below)
|
||||
|
||||
We appreciate any and all contributions to the test suite!
|
||||
|
||||
@ -744,6 +739,26 @@ If you're using another backend:
|
||||
deleted when the tests are finished. This means your user account needs
|
||||
permission to execute ``CREATE DATABASE``.
|
||||
|
||||
If you want to run the full suite of tests, there are a number of dependencies that
|
||||
you should install:
|
||||
|
||||
* PyYAML_
|
||||
* Markdown_
|
||||
* Textile_
|
||||
* Docutils_
|
||||
* setuptools_
|
||||
|
||||
Of these dependencies, setuptools_ is the only dependency that is required - if
|
||||
setuptools_ is not installed, you will get import errors when running one of
|
||||
the template tests. The tests using the other libraries will be skipped if the
|
||||
dependency can't be found.
|
||||
|
||||
.. _PyYAML: http://pyyaml.org/wiki/PyYAML
|
||||
.. _Markdown: http://pypi.python.org/pypi/Markdown/1.7
|
||||
.. _Textile: http://pypi.python.org/pypi/textile
|
||||
.. _docutils: http://pypi.python.org/pypi/docutils/0.4
|
||||
.. _setuptools: http://pypi.python.org/pypi/setuptools/
|
||||
|
||||
To run a subset of the unit tests, append the names of the test modules to the
|
||||
``runtests.py`` command line. See the list of directories in
|
||||
``tests/modeltests`` and ``tests/regressiontests`` for module names.
|
||||
@ -755,6 +770,22 @@ for generic relations and internationalization, type::
|
||||
PYTHONPATH=..
|
||||
./runtests.py --settings=settings generic_relations i18n
|
||||
|
||||
Contrib apps
|
||||
------------
|
||||
|
||||
Tests for apps in ``django/contrib/`` go in their respective directories,
|
||||
in a ``tests.py`` file. (You can split the tests over multiple modules
|
||||
by using a ``tests`` folder in the normal Python way).
|
||||
|
||||
For the tests to be found, a ``models.py`` file must exist (it doesn't
|
||||
have to have anything in it). If you have URLs that need to be
|
||||
mapped, you must add them in ``tests/urls.py``.
|
||||
|
||||
To run tests for just one contrib app (e.g. ``markup``), use the same
|
||||
method as above::
|
||||
|
||||
./runtests.py --settings=settings markup
|
||||
|
||||
Requesting features
|
||||
===================
|
||||
|
||||
|
@ -1382,7 +1382,7 @@ and then converted into a query using the ``query`` attribute::
|
||||
|
||||
This queryset will be evaluated as subselect statement::
|
||||
|
||||
SELET ... WHERE blog.id IN (SELECT id FROM ... WHERE NAME LIKE '%Cheddar%')
|
||||
SELECT ... WHERE blog.id IN (SELECT id FROM ... WHERE NAME LIKE '%Cheddar%')
|
||||
|
||||
startswith
|
||||
~~~~~~~~~~
|
||||
|
@ -648,8 +648,8 @@ Django will automatically add this field::
|
||||
Thus, you don't need to set ``primary_key=True`` on any of your fields
|
||||
unless you want to override the default primary-key behavior.
|
||||
|
||||
``primary_key=True`` implies ``blank=False``, ``null=False`` and
|
||||
``unique=True``. Only one primary key is allowed on an object.
|
||||
``primary_key=True`` implies ``null=False`` and ``unique=True``. Only
|
||||
one primary key is allowed on an object.
|
||||
|
||||
``unique``
|
||||
~~~~~~~~~~
|
||||
|
@ -182,6 +182,13 @@ supplied, ``save()`` will update that instance. If it's not supplied,
|
||||
# Create a form to edit an existing Article.
|
||||
>>> a = Article.objects.get(pk=1)
|
||||
>>> f = ArticleForm(instance=a)
|
||||
>>> f.save()
|
||||
|
||||
# Create a form to edit an existing Article, but use
|
||||
# POST data to populate the form.
|
||||
>>> a = Article.objects.get(pk=1)
|
||||
>>> f = ArticleForm(request.POST, instance=a)
|
||||
>>> f.save()
|
||||
|
||||
Note that ``save()`` will raise a ``ValueError`` if the data in the form
|
||||
doesn't validate -- i.e., ``if form.errors``.
|
||||
|
@ -44,7 +44,7 @@ _django_completion()
|
||||
# Standalone options
|
||||
opts="--help --settings --pythonpath --noinput --noreload --format --indent --verbosity --adminmedia --version"
|
||||
# Actions
|
||||
actions="adminindex createcachetable dbshell diffsettings \
|
||||
actions="adminindex createcachetable createsuperuser dbshell diffsettings \
|
||||
dumpdata flush inspectdb loaddata reset runfcgi runserver \
|
||||
shell sql sqlall sqlclear sqlcustom sqlflush sqlindexes \
|
||||
sqlreset sqlsequencereset startapp startproject \
|
||||
|
1
tests/modeltests/delete/__init__.py
Normal file
1
tests/modeltests/delete/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
|
179
tests/modeltests/delete/models.py
Normal file
179
tests/modeltests/delete/models.py
Normal file
@ -0,0 +1,179 @@
|
||||
# coding: utf-8
|
||||
"""
|
||||
Tests for some corner cases with deleting.
|
||||
"""
|
||||
|
||||
from django.db import models
|
||||
|
||||
class DefaultRepr(object):
|
||||
def __repr__(self):
|
||||
return u"<%s: %s>" % (self.__class__.__name__, self.__dict__)
|
||||
|
||||
class A(DefaultRepr, models.Model):
|
||||
pass
|
||||
|
||||
class B(DefaultRepr, models.Model):
|
||||
a = models.ForeignKey(A)
|
||||
|
||||
class C(DefaultRepr, models.Model):
|
||||
b = models.ForeignKey(B)
|
||||
|
||||
class D(DefaultRepr, models.Model):
|
||||
c = models.ForeignKey(C)
|
||||
a = models.ForeignKey(A)
|
||||
|
||||
# Simplified, we have:
|
||||
# A
|
||||
# B -> A
|
||||
# C -> B
|
||||
# D -> C
|
||||
# D -> A
|
||||
|
||||
# So, we must delete Ds first of all, then Cs then Bs then As.
|
||||
# However, if we start at As, we might find Bs first (in which
|
||||
# case things will be nice), or find Ds first.
|
||||
|
||||
# Some mutually dependent models, but nullable
|
||||
class E(DefaultRepr, models.Model):
|
||||
f = models.ForeignKey('F', null=True, related_name='e_rel')
|
||||
|
||||
class F(DefaultRepr, models.Model):
|
||||
e = models.ForeignKey(E, related_name='f_rel')
|
||||
|
||||
|
||||
__test__ = {'API_TESTS': """
|
||||
# First, some tests for the datastructure we use
|
||||
|
||||
>>> from django.db.models.query import CollectedObjects
|
||||
|
||||
>>> g = CollectedObjects()
|
||||
>>> g.add("key1", 1, "item1", None)
|
||||
False
|
||||
>>> g["key1"]
|
||||
{1: 'item1'}
|
||||
>>> g.add("key2", 1, "item1", "key1")
|
||||
False
|
||||
>>> g.add("key2", 2, "item2", "key1")
|
||||
False
|
||||
>>> g["key2"]
|
||||
{1: 'item1', 2: 'item2'}
|
||||
>>> g.add("key3", 1, "item1", "key1")
|
||||
False
|
||||
>>> g.add("key3", 1, "item1", "key2")
|
||||
True
|
||||
>>> g.ordered_keys()
|
||||
['key3', 'key2', 'key1']
|
||||
|
||||
>>> g.add("key2", 1, "item1", "key3")
|
||||
True
|
||||
>>> g.ordered_keys()
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
CyclicDependency: There is a cyclic dependency of items to be processed.
|
||||
|
||||
|
||||
|
||||
# Due to the way that transactions work in the test harness,
|
||||
# doing m.delete() here can work but fail in a real situation,
|
||||
# since it may delete all objects, but not in the right order.
|
||||
# So we manually check that the order of deletion is correct.
|
||||
|
||||
# Also, it is possible that the order is correct 'accidentally', due
|
||||
# solely to order of imports etc. To check this, we set the order
|
||||
# that 'get_models()' will retrieve to a known 'nice' order, and
|
||||
# then try again with a known 'tricky' order. Slightly naughty
|
||||
# access to internals here :-)
|
||||
|
||||
>>> from django.db.models.loading import cache
|
||||
|
||||
# Nice order
|
||||
>>> cache.app_models['delete'].keyOrder = ['a', 'b', 'c', 'd']
|
||||
>>> del A._meta._related_objects_cache
|
||||
>>> del B._meta._related_objects_cache
|
||||
>>> del C._meta._related_objects_cache
|
||||
>>> del D._meta._related_objects_cache
|
||||
|
||||
>>> a1 = A()
|
||||
>>> a1.save()
|
||||
>>> b1 = B(a=a1)
|
||||
>>> b1.save()
|
||||
>>> c1 = C(b=b1)
|
||||
>>> c1.save()
|
||||
>>> d1 = D(c=c1, a=a1)
|
||||
>>> d1.save()
|
||||
|
||||
>>> o = CollectedObjects()
|
||||
>>> a1._collect_sub_objects(o)
|
||||
>>> o.keys()
|
||||
[<class 'modeltests.delete.models.D'>, <class 'modeltests.delete.models.C'>, <class 'modeltests.delete.models.B'>, <class 'modeltests.delete.models.A'>]
|
||||
>>> a1.delete()
|
||||
|
||||
# Same again with a known bad order
|
||||
>>> cache.app_models['delete'].keyOrder = ['d', 'c', 'b', 'a']
|
||||
>>> del A._meta._related_objects_cache
|
||||
>>> del B._meta._related_objects_cache
|
||||
>>> del C._meta._related_objects_cache
|
||||
>>> del D._meta._related_objects_cache
|
||||
|
||||
>>> a2 = A()
|
||||
>>> a2.save()
|
||||
>>> b2 = B(a=a2)
|
||||
>>> b2.save()
|
||||
>>> c2 = C(b=b2)
|
||||
>>> c2.save()
|
||||
>>> d2 = D(c=c2, a=a2)
|
||||
>>> d2.save()
|
||||
|
||||
>>> o = CollectedObjects()
|
||||
>>> a2._collect_sub_objects(o)
|
||||
>>> o.keys()
|
||||
[<class 'modeltests.delete.models.D'>, <class 'modeltests.delete.models.C'>, <class 'modeltests.delete.models.B'>, <class 'modeltests.delete.models.A'>]
|
||||
>>> a2.delete()
|
||||
|
||||
# Tests for nullable related fields
|
||||
|
||||
>>> g = CollectedObjects()
|
||||
>>> g.add("key1", 1, "item1", None)
|
||||
False
|
||||
>>> g.add("key2", 1, "item1", "key1", nullable=True)
|
||||
False
|
||||
>>> g.add("key1", 1, "item1", "key2")
|
||||
True
|
||||
>>> g.ordered_keys()
|
||||
['key1', 'key2']
|
||||
|
||||
>>> e1 = E()
|
||||
>>> e1.save()
|
||||
>>> f1 = F(e=e1)
|
||||
>>> f1.save()
|
||||
>>> e1.f = f1
|
||||
>>> e1.save()
|
||||
|
||||
# Since E.f is nullable, we should delete F first (after nulling out
|
||||
# the E.f field), then E.
|
||||
|
||||
>>> o = CollectedObjects()
|
||||
>>> e1._collect_sub_objects(o)
|
||||
>>> o.keys()
|
||||
[<class 'modeltests.delete.models.F'>, <class 'modeltests.delete.models.E'>]
|
||||
|
||||
>>> e1.delete()
|
||||
|
||||
>>> e2 = E()
|
||||
>>> e2.save()
|
||||
>>> f2 = F(e=e2)
|
||||
>>> f2.save()
|
||||
>>> e2.f = f2
|
||||
>>> e2.save()
|
||||
|
||||
# Same deal as before, though we are starting from the other object.
|
||||
|
||||
>>> o = CollectedObjects()
|
||||
>>> f2._collect_sub_objects(o)
|
||||
>>> o.keys()
|
||||
[<class 'modeltests.delete.models.F'>, <class 'modeltests.delete.models.E'>]
|
||||
|
||||
>>> f2.delete()
|
||||
|
||||
"""
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user