1
0
mirror of https://github.com/django/django.git synced 2025-07-05 10:19:20 +00:00

Merged to trunk r1234

git-svn-id: http://code.djangoproject.com/svn/django/branches/new-admin@1235 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Robert Wittams 2005-11-15 01:36:12 +00:00
commit 35d90bfdc7
23 changed files with 2000 additions and 295 deletions

View File

@ -7,8 +7,10 @@ DOCUMENTATION_DIRECTORY = '/home/html/documentation/'
def clean_up(): def clean_up():
# Clean up old database records # Clean up old database records
cursor = db.cursor() cursor = db.cursor()
cursor.execute("DELETE FROM core_sessions WHERE expire_date < NOW()") cursor.execute("DELETE FROM %s WHERE %s < NOW()" % \
cursor.execute("DELETE FROM registration_challenges WHERE request_date < NOW() - INTERVAL '1 week'") (db.quote_name('core_sessions'), db.quote_name('expire_date')))
cursor.execute("DELETE FROM %s WHERE %s < NOW() - INTERVAL '1 week'" % \
(db.quote_name('registration_challenges'), db.quote_name('request_date')))
db.commit() db.commit()
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -14,8 +14,7 @@ msgstr ""
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n" "Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"X-Poedit-Language: Czech\n" "X-Poedit-Language: Czech\n"
"X-Poedit-Country: CZECH REPUBLIC\n" "X-Poedit-Country: CZECH REPUBLIC\n"
@ -263,12 +262,8 @@ msgid "Server Error <em>(500)</em>"
msgstr "Chyba serveru <em>(500)</em>" msgstr "Chyba serveru <em>(500)</em>"
#: contrib/admin/templates/admin/500.html:10 #: contrib/admin/templates/admin/500.html:10
msgid "" msgid "There's been an error. It's been reported to the site administrators via e-mail and should be fixed shortly. Thanks for your patience."
"There's been an error. It's been reported to the site administrators via e-" msgstr "Nastala chyba. Ta byla oznámena administrátorovi serveru pomocí e-mailu a měla by být brzy odstraněna. Děkujeme za trpělivost."
"mail and should be fixed shortly. Thanks for your patience."
msgstr ""
"Nastala chyba. Ta byla oznámena administrátorovi serveru pomocí e-mailu a "
"měla by být brzy odstraněna. Děkujeme za trpělivost."
#: contrib/admin/templates/admin/404.html:4 #: contrib/admin/templates/admin/404.html:4
#: contrib/admin/templates/admin/404.html:8 #: contrib/admin/templates/admin/404.html:8
@ -359,13 +354,8 @@ msgstr "Odhlásit se"
#: contrib/admin/templates/admin/delete_confirmation.html:7 #: contrib/admin/templates/admin/delete_confirmation.html:7
#, fuzzy, python-format #, fuzzy, python-format
msgid "" msgid "Deleting the %(object_name)s '%(object)s' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:"
"Deleting the %(object_name)s '%(object)s' would result in deleting related " msgstr "Mazání %(object_name)s '%(object)s' by vyústilo ve vymazání souvisejících objektů, ale Váš účet nemá oprávnění pro mazání následujících typů objektů:"
"objects, but your account doesn't have permission to delete the following "
"types of objects:"
msgstr ""
"Mazání %(object_name)s '%(object)s' by vyústilo ve vymazání souvisejících "
"objektů, ale Váš účet nemá oprávnění pro mazání následujících typů objektů:"
#: contrib/admin/templates/admin/change_form.html:20 #: contrib/admin/templates/admin/change_form.html:20
msgid "View on site" msgid "View on site"
@ -408,12 +398,8 @@ msgstr "aktivní"
#: contrib/admin/templates/admin/delete_confirmation.html:14 #: contrib/admin/templates/admin/delete_confirmation.html:14
#, python-format #, python-format
msgid "" msgid "Are you sure you want to delete the %(object_name)s \"%(object)s\"? All of the following related items will be deleted:"
"Are you sure you want to delete the %(object_name)s \"%(object)s\"? All of " msgstr "Jste si jist(á), že chcete smazat %(object_name)s \"%(object)s\"? Všechny následující související položky budou smazány:"
"the following related items will be deleted:"
msgstr ""
"Jste si jist(á), že chcete smazat %(object_name)s \"%(object)s\"? Všechny "
"následující související položky budou smazány:"
#: contrib/admin/templates/admin/delete_confirmation.html:18 #: contrib/admin/templates/admin/delete_confirmation.html:18
msgid "Yes, I'm sure" msgid "Yes, I'm sure"
@ -442,12 +428,8 @@ msgid "Password reset"
msgstr "Obnovení hesla" msgstr "Obnovení hesla"
#: contrib/admin/templates/registration/password_reset_form.html:12 #: contrib/admin/templates/registration/password_reset_form.html:12
msgid "" msgid "Forgotten your password? Enter your e-mail address below, and we'll reset your password and e-mail the new one to you."
"Forgotten your password? Enter your e-mail address below, and we'll reset " msgstr "Zapomněl(a) jste heslo? Vložte níže Vaši e-mailovou adresu a my Vaše heslo obnovíme a zašleme Vám e-mailem nové."
"your password and e-mail the new one to you."
msgstr ""
"Zapomněl(a) jste heslo? Vložte níže Vaši e-mailovou adresu a my Vaše heslo "
"obnovíme a zašleme Vám e-mailem nové."
#: contrib/admin/templates/registration/password_reset_form.html:16 #: contrib/admin/templates/registration/password_reset_form.html:16
msgid "E-mail address:" msgid "E-mail address:"
@ -471,20 +453,12 @@ msgid "Password reset successful"
msgstr "Obnovení hesla bylo úspěšné" msgstr "Obnovení hesla bylo úspěšné"
#: contrib/admin/templates/registration/password_reset_done.html:12 #: contrib/admin/templates/registration/password_reset_done.html:12
msgid "" msgid "We've e-mailed a new password to the e-mail address you submitted. You should be receiving it shortly."
"We've e-mailed a new password to the e-mail address you submitted. You " msgstr "Poslali jsme Vám e-mailem nové heslo na adresu, kterou jste zadal(a). Měl(a) byste ji dostat během okamžiku."
"should be receiving it shortly."
msgstr ""
"Poslali jsme Vám e-mailem nové heslo na adresu, kterou jste zadal(a). Měl(a) "
"byste ji dostat během okamžiku."
#: contrib/admin/templates/registration/password_change_form.html:12 #: contrib/admin/templates/registration/password_change_form.html:12
msgid "" msgid "Please enter your old password, for security's sake, and then enter your new password twice so we can verify you typed it in correctly."
"Please enter your old password, for security's sake, and then enter your new " msgstr "Prosíme, pro zabezpečení vložte svoje staré heslo a poté vložte dvakrát nové heslo, takže můžeme ověřit, že jste ho napsal(a) správně."
"password twice so we can verify you typed it in correctly."
msgstr ""
"Prosíme, pro zabezpečení vložte svoje staré heslo a poté vložte dvakrát nové "
"heslo, takže můžeme ověřit, že jste ho napsal(a) správně."
#: contrib/admin/templates/registration/password_change_form.html:17 #: contrib/admin/templates/registration/password_change_form.html:17
msgid "Old password:" msgid "Old password:"
@ -567,15 +541,15 @@ msgstr ""
#: utils/translation.py:335 #: utils/translation.py:335
msgid "DATE_FORMAT" msgid "DATE_FORMAT"
msgstr "" msgstr "Formát data"
#: utils/translation.py:336 #: utils/translation.py:336
msgid "DATETIME_FORMAT" msgid "DATETIME_FORMAT"
msgstr "" msgstr "Formát data a času"
#: utils/translation.py:337 #: utils/translation.py:337
msgid "TIME_FORMAT" msgid "TIME_FORMAT"
msgstr "" msgstr "Formát času"
#: utils/dates.py:6 #: utils/dates.py:6
msgid "Monday" msgid "Monday"
@ -613,23 +587,28 @@ msgstr "Leden"
msgid "February" msgid "February"
msgstr "Únor" msgstr "Únor"
#: utils/dates.py:14 utils/dates.py:27 #: utils/dates.py:14
#: utils/dates.py:27
msgid "March" msgid "March"
msgstr "Březen" msgstr "Březen"
#: utils/dates.py:14 utils/dates.py:27 #: utils/dates.py:14
#: utils/dates.py:27
msgid "April" msgid "April"
msgstr "Duben" msgstr "Duben"
#: utils/dates.py:14 utils/dates.py:27 #: utils/dates.py:14
#: utils/dates.py:27
msgid "May" msgid "May"
msgstr "Květen" msgstr "Květen"
#: utils/dates.py:14 utils/dates.py:27 #: utils/dates.py:14
#: utils/dates.py:27
msgid "June" msgid "June"
msgstr "Červen" msgstr "Červen"
#: utils/dates.py:15 utils/dates.py:27 #: utils/dates.py:15
#: utils/dates.py:27
msgid "July" msgid "July"
msgstr "Červenec" msgstr "Červenec"
@ -701,7 +680,10 @@ msgstr "weby"
msgid "label" msgid "label"
msgstr "nadpis" msgstr "nadpis"
#: models/core.py:29 models/core.py:40 models/auth.py:6 models/auth.py:19 #: models/core.py:29
#: models/core.py:40
#: models/auth.py:6
#: models/auth.py:19
msgid "name" msgid "name"
msgstr "jméno" msgstr "jméno"
@ -832,7 +814,8 @@ msgstr "codename"
msgid "Permission" msgid "Permission"
msgstr "Oprávnění" msgstr "Oprávnění"
#: models/auth.py:11 models/auth.py:58 #: models/auth.py:11
#: models/auth.py:58
msgid "Permissions" msgid "Permissions"
msgstr "Oprávnění" msgstr "Oprávnění"
@ -840,7 +823,8 @@ msgstr "Oprávnění"
msgid "Group" msgid "Group"
msgstr "Skupina" msgstr "Skupina"
#: models/auth.py:23 models/auth.py:60 #: models/auth.py:23
#: models/auth.py:60
msgid "Groups" msgid "Groups"
msgstr "Skupiny" msgstr "Skupiny"
@ -894,12 +878,8 @@ msgid "date joined"
msgstr "datum zaregistrování" msgstr "datum zaregistrování"
#: models/auth.py:44 #: models/auth.py:44
msgid "" msgid "In addition to the permissions manually assigned, this user will also get all permissions granted to each group he/she is in."
"In addition to the permissions manually assigned, this user will also get " msgstr "Kromě manuálně přidělených oprávnění uživatel dostane všechna oprávnění pro každou skupinu, ve které je."
"all permissions granted to each group he/she is in."
msgstr ""
"Kromě manuálně přidělených oprávnění uživatel dostane všechna oprávnění pro "
"každou skupinu, ve které je."
#: models/auth.py:48 #: models/auth.py:48
msgid "Users" msgid "Users"
@ -951,7 +931,7 @@ msgstr "Galicijsky"
#: conf/global_settings.py:44 #: conf/global_settings.py:44
msgid "Icelandic" msgid "Icelandic"
msgstr "" msgstr "Islandština"
#: conf/global_settings.py:45 #: conf/global_settings.py:45
msgid "Italian" msgid "Italian"
@ -987,8 +967,7 @@ msgstr "Tato hodnota musí obsahovat pouze znaky, čísla nebo podtržítka."
#: core/validators.py:63 #: core/validators.py:63
msgid "This value must contain only letters, numbers, underscores and slashes." msgid "This value must contain only letters, numbers, underscores and slashes."
msgstr "" msgstr "Tato hodnota musí obsahovat pouze znaky, čísla, podtržítka nebo lomítka."
"Tato hodnota musí obsahovat pouze znaky, čísla, podtržítka nebo lomítka."
#: core/validators.py:71 #: core/validators.py:71
msgid "Uppercase letters are not allowed here." msgid "Uppercase letters are not allowed here."
@ -1047,12 +1026,8 @@ msgid "Enter a valid e-mail address."
msgstr "Vložte platnou e-mailovou adresu." msgstr "Vložte platnou e-mailovou adresu."
#: core/validators.py:147 #: core/validators.py:147
msgid "" msgid "Upload a valid image. The file you uploaded was either not an image or a corrupted image."
"Upload a valid image. The file you uploaded was either not an image or a " msgstr "Nahrajte na server platný obrázek. Soubor, který jste nahrál(a) nebyl obrázek, nebo byl porušen."
"corrupted image."
msgstr ""
"Nahrajte na server platný obrázek. Soubor, který jste nahrál(a) nebyl "
"obrázek, nebo byl porušen."
#: core/validators.py:154 #: core/validators.py:154
#, python-format #, python-format
@ -1092,7 +1067,8 @@ msgstr "Špatně formované XML: %s"
msgid "Invalid URL: %s" msgid "Invalid URL: %s"
msgstr "Neplatné URL: %s" msgstr "Neplatné URL: %s"
#: core/validators.py:205 core/validators.py:207 #: core/validators.py:205
#: core/validators.py:207
#, python-format #, python-format
msgid "The URL %s is a broken link." msgid "The URL %s is a broken link."
msgstr "Odkaz na URL %s je rozbitý." msgstr "Odkaz na URL %s je rozbitý."
@ -1118,7 +1094,8 @@ msgstr "Toto pole se musí shodovat s polem '%s'."
msgid "Please enter something for at least one field." msgid "Please enter something for at least one field."
msgstr "Prosíme, vložte něco alespoň pro jedno pole." msgstr "Prosíme, vložte něco alespoň pro jedno pole."
#: core/validators.py:263 core/validators.py:274 #: core/validators.py:263
#: core/validators.py:274
msgid "Please enter both fields or leave them both empty." msgid "Please enter both fields or leave them both empty."
msgstr "Prosíme, vložte obě pole, nebo je nechte obě prázdná." msgstr "Prosíme, vložte obě pole, nebo je nechte obě prázdná."
@ -1148,8 +1125,7 @@ msgstr "Prosíme, vložte platné číslo."
#: core/validators.py:348 #: core/validators.py:348
#, python-format #, python-format
msgid "Please enter a valid decimal number with at most %s total digit." msgid "Please enter a valid decimal number with at most %s total digit."
msgid_plural "" msgid_plural "Please enter a valid decimal number with at most %s total digits."
"Please enter a valid decimal number with at most %s total digits."
msgstr[0] "Prosíme, vložte platné číslo s nejvíce %s cifrou celkem." msgstr[0] "Prosíme, vložte platné číslo s nejvíce %s cifrou celkem."
msgstr[1] "Prosíme, vložte platné číslo s nejvíce %s ciframi celkem." msgstr[1] "Prosíme, vložte platné číslo s nejvíce %s ciframi celkem."
msgstr[2] "Prosíme, vložte platné číslo s nejvíce %s ciframi celkem." msgstr[2] "Prosíme, vložte platné číslo s nejvíce %s ciframi celkem."
@ -1157,16 +1133,10 @@ msgstr[2] "Prosíme, vložte platné číslo s nejvíce %s ciframi celkem."
#: core/validators.py:351 #: core/validators.py:351
#, python-format #, python-format
msgid "Please enter a valid decimal number with at most %s decimal place." msgid "Please enter a valid decimal number with at most %s decimal place."
msgid_plural "" msgid_plural "Please enter a valid decimal number with at most %s decimal places."
"Please enter a valid decimal number with at most %s decimal places." msgstr[0] "Prosíme, vložte platné číslo s nejvíce %s cifrou za desetinnou čárkou celkem."
msgstr[0] "" msgstr[1] "Prosíme, vložte platné číslo s nejvíce %s ciframi za desetinnou čárkou celkem."
"Prosíme, vložte platné číslo s nejvíce %s cifrou za desetinnou čárkou celkem." msgstr[2] "Prosíme, vložte platné číslo s nejvíce %s ciframi za desetinnou čárkou celkem."
msgstr[1] ""
"Prosíme, vložte platné číslo s nejvíce %s ciframi za desetinnou čárkou "
"celkem."
msgstr[2] ""
"Prosíme, vložte platné číslo s nejvíce %s ciframi za desetinnou čárkou "
"celkem."
#: core/validators.py:361 #: core/validators.py:361
#, python-format #, python-format
@ -1193,71 +1163,44 @@ msgstr "Nemohl jsem získat nic z %s."
#: core/validators.py:428 #: core/validators.py:428
#, python-format #, python-format
msgid "" msgid "The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
"The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
msgstr "URL %(url)s vrátilo neplatnou hlavičku Content-Type '%(contenttype)s'." msgstr "URL %(url)s vrátilo neplatnou hlavičku Content-Type '%(contenttype)s'."
#: core/validators.py:461 #: core/validators.py:461
#, python-format #, python-format
msgid "" msgid "Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with \"%(start)s\".)"
"Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with " msgstr "Prosíme, zavřete nezavřenou značku %(tag)s z řádky %(line)s. (Řádka začíná s \"%(start)s\".)"
"\"%(start)s\".)"
msgstr ""
"Prosíme, zavřete nezavřenou značku %(tag)s z řádky %(line)s. (Řádka začíná s "
"\"%(start)s\".)"
#: core/validators.py:465 #: core/validators.py:465
#, python-format #, python-format
msgid "" msgid "Some text starting on line %(line)s is not allowed in that context. (Line starts with \"%(start)s\".)"
"Some text starting on line %(line)s is not allowed in that context. (Line " msgstr "Nějaký text začínající na řádce %(line)s není povolen v tomto kontextu. (Řádka začíná s \"%(start)s\".)"
"starts with \"%(start)s\".)"
msgstr ""
"Nějaký text začínající na řádce %(line)s není povolen v tomto kontextu. "
"(Řádka začíná s \"%(start)s\".)"
#: core/validators.py:470 #: core/validators.py:470
#, python-format #, python-format
msgid "" msgid "\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%(start)s\".)"
"\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%" msgstr "\"%(attr)s\" na řádce %(line)s je neplatný atribut. (Řádka začíná s \"%(start)s\".)"
"(start)s\".)"
msgstr ""
"\"%(attr)s\" na řádce %(line)s je neplatný atribut. (Řádka začíná s \"%"
"(start)s\".)"
#: core/validators.py:475 #: core/validators.py:475
#, python-format #, python-format
msgid "" msgid "\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%(start)s\".)"
"\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%" msgstr "\"<%(tag)s>\" na řádce %(line)s je neplatná značka. (Řádka začíná s \"%(start)s\".)"
"(start)s\".)"
msgstr ""
"\"<%(tag)s>\" na řádce %(line)s je neplatná značka. (Řádka začíná s \"%"
"(start)s\".)"
#: core/validators.py:479 #: core/validators.py:479
#, python-format #, python-format
msgid "" msgid "A tag on line %(line)s is missing one or more required attributes. (Line starts with \"%(start)s\".)"
"A tag on line %(line)s is missing one or more required attributes. (Line " msgstr "Značce na řádce %(line)s schází jeden nebo více požadovaných atributů. (Řádka začíná s \"%(start)s\".)"
"starts with \"%(start)s\".)"
msgstr ""
"Značce na řádce %(line)s schází jeden nebo více požadovaných atributů. "
"(Řádka začíná s \"%(start)s\".)"
#: core/validators.py:484 #: core/validators.py:484
#, python-format #, python-format
msgid "" msgid "The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line starts with \"%(start)s\".)"
"The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line " msgstr "Atribut \"%(attr)s\" na řádce %(line)s má neplatnou hodnotu. (Řádka začína s \"%(start)s\".)"
"starts with \"%(start)s\".)"
msgstr ""
"Atribut \"%(attr)s\" na řádce %(line)s má neplatnou hodnotu. (Řádka začína s "
"\"%(start)s\".)"
#: core/meta/fields.py:114 #: core/meta/fields.py:114
msgid " Separate multiple IDs with commas." msgid " Separate multiple IDs with commas."
msgstr "Oddělte více identifikátorů čárkami." msgstr "Oddělte více identifikátorů čárkami."
#: core/meta/fields.py:117 #: core/meta/fields.py:117
msgid "" msgid " Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
" Hold down \"Control\", or \"Command\" on a Mac, to select more than one." msgstr "Podržte \"Control\", nebo \"Command\" na Macu pro vybrání více jak jedné položky."
msgstr ""
"Podržte \"Control\", nebo \"Command\" na Macu pro vybrání více jak jedné "
"položky."

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -11,7 +11,7 @@ msgstr ""
"POT-Creation-Date: 2005-11-08 09:05-0600\n" "POT-Creation-Date: 2005-11-08 09:05-0600\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Vladimir Labath <vlado@labath.org>\n" "Last-Translator: Vladimir Labath <vlado@labath.org>\n"
"Language-Team: Slovak <info@labath.org>\n" "Language-Team: Slovak <sk@li.org>\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n" "Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
@ -568,18 +568,6 @@ msgstr "záznamy priebehu"
msgid "All dates" msgid "All dates"
msgstr "" msgstr ""
#: utils/translation.py:335
msgid "DATE_FORMAT"
msgstr ""
#: utils/translation.py:336
msgid "DATETIME_FORMAT"
msgstr ""
#: utils/translation.py:337
msgid "TIME_FORMAT"
msgstr ""
#: utils/dates.py:6 #: utils/dates.py:6
msgid "Monday" msgid "Monday"
msgstr "Pondelok" msgstr "Pondelok"
@ -684,6 +672,18 @@ msgstr ""
msgid "Dec." msgid "Dec."
msgstr "" msgstr ""
#: utils/translation.py:335
msgid "DATE_FORMAT"
msgstr "DATUM_FORMAT"
#: utils/translation.py:336
msgid "DATETIME_FORMAT"
msgstr "DATUMCAS_FORMAT"
#: utils/translation.py:337
msgid "TIME_FORMAT"
msgstr "CAS_FORMAT"
#: models/core.py:7 #: models/core.py:7
msgid "domain name" msgid "domain name"
msgstr "meno domény" msgstr "meno domény"
@ -916,7 +916,7 @@ msgstr "Osobné údaje"
msgid "Important dates" msgid "Important dates"
msgstr "Dôležité údaje" msgstr "Dôležité údaje"
#: models/auth.py:182 #: models/auth.py:195
msgid "Message" msgid "Message"
msgstr "Zpráva" msgstr "Zpráva"

View File

@ -209,9 +209,9 @@ def items_for_result(cl, result):
result_repr = '&nbsp;' result_repr = '&nbsp;'
if first: # First column is a special case if first: # First column is a special case
first = False first = False
result_id = getattr(result, pk) url = cl.url_for_result(result)
yield ('<th%s><a href="%s/"%s>%s</a></th>' % \ yield ('<th%s><a href="%s"%s>%s</a></th>' % \
(row_class, result_id, (cl.is_popup and ' onclick="opener.dismissRelatedLookupPopup(window, %r); return false;"' % result_id or ''), result_repr)) (row_class, url, (cl.is_popup and ' onclick="opener.dismissRelatedLookupPopup(window, %r); return false;"' % result_id or ''), result_repr))
else: else:
yield ('<td%s>%s</td>' % (row_class, result_repr)) yield ('<td%s>%s</td>' % (row_class, result_repr))

View File

@ -208,6 +208,7 @@ class ChangeList(object):
and _('Select %s') % self.opts.verbose_name and _('Select %s') % self.opts.verbose_name
or _('Select %s to change') % self.opts.verbose_name) or _('Select %s to change') % self.opts.verbose_name)
self.get_filters(request) self.get_filters(request)
self.pk_attname = self.lookup_opts.pk.attname
def get_filters(self, request): def get_filters(self, request):
self.filter_specs = [] self.filter_specs = []
@ -301,6 +302,9 @@ class ChangeList(object):
self.can_show_all, self.multi_page, self.paginator) = (result_count, self.can_show_all, self.multi_page, self.paginator) = (result_count,
full_result_count, result_list, can_show_all, multi_page, paginator ) full_result_count, result_list, can_show_all, multi_page, paginator )
def url_for_result(self, result):
return "%s/" % getattr(result, self.pk_attname)
def get_ordering(self): def get_ordering(self):
lookup_opts, params = self.lookup_opts, self.params lookup_opts, params = self.lookup_opts, self.params
# For ordering, first check the "ordering" parameter in the admin options, # For ordering, first check the "ordering" parameter in the admin options,

View File

@ -17,8 +17,9 @@ class Feed:
item_enclosure_url = None item_enclosure_url = None
feed_type = feedgenerator.DefaultFeed feed_type = feedgenerator.DefaultFeed
def __init__(self, slug): def __init__(self, slug, feed_url):
self.slug = slug self.slug = slug
self.feed_url = feed_url
def item_link(self, item): def item_link(self, item):
try: try:
@ -26,8 +27,11 @@ class Feed:
except AttributeError: except AttributeError:
raise ImproperlyConfigured, "Give your %s class a get_absolute_url() method, or define an item_link() method in your Feed class." % item.__class__.__name__ raise ImproperlyConfigured, "Give your %s class a get_absolute_url() method, or define an item_link() method in your Feed class." % item.__class__.__name__
def __get_dynamic_attr(self, attname, obj): def __get_dynamic_attr(self, attname, obj, default=None):
try:
attr = getattr(self, attname) attr = getattr(self, attname)
except AttributeError:
return default
if callable(attr): if callable(attr):
try: try:
return attr(obj) return attr(obj)
@ -56,7 +60,11 @@ class Feed:
title = self.__get_dynamic_attr('title', obj), title = self.__get_dynamic_attr('title', obj),
link = link, link = link,
description = self.__get_dynamic_attr('description', obj), description = self.__get_dynamic_attr('description', obj),
language = LANGUAGE_CODE.decode() language = LANGUAGE_CODE.decode(),
feed_url = add_domain(current_site, self.feed_url),
author_name = self.__get_dynamic_attr('author_name', obj),
author_link = self.__get_dynamic_attr('author_link', obj),
author_email = self.__get_dynamic_attr('author_email', obj),
) )
try: try:
@ -78,6 +86,12 @@ class Feed:
length = str(self.__get_dynamic_attr('item_enclosure_length', item)).decode('utf-8'), length = str(self.__get_dynamic_attr('item_enclosure_length', item)).decode('utf-8'),
mime_type = self.__get_dynamic_attr('item_enclosure_mime_type', item).decode('utf-8'), mime_type = self.__get_dynamic_attr('item_enclosure_mime_type', item).decode('utf-8'),
) )
author_name = self.__get_dynamic_attr('item_author_name', item)
if author_name is not None:
author_email = self.__get_dynamic_attr('item_author_email', item)
author_link = self.__get_dynamic_attr('item_author_link', item)
else:
author_email = author_link = None
feed.add_item( feed.add_item(
title = title_template.render(Context({'obj': item, 'site': current_site})).decode('utf-8'), title = title_template.render(Context({'obj': item, 'site': current_site})).decode('utf-8'),
link = link, link = link,
@ -85,5 +99,8 @@ class Feed:
unique_id = link, unique_id = link,
enclosure = enc, enclosure = enc,
pubdate = self.__get_dynamic_attr('item_pubdate', item), pubdate = self.__get_dynamic_attr('item_pubdate', item),
author_name = author_name,
author_email = author_email,
author_link = author_link,
) )
return feed return feed

View File

@ -17,7 +17,7 @@ def feed(request, url, feed_dict=None):
raise Http404, "Slug %r isn't registered." % slug raise Http404, "Slug %r isn't registered." % slug
try: try:
feedgen = f(slug).get_feed(param) feedgen = f(slug, request.path).get_feed(param)
except feeds.FeedDoesNotExist: except feeds.FeedDoesNotExist:
raise Http404, "Invalid feed parameters. Slug %r is valid, but other parameters, or lack thereof, are not." % slug raise Http404, "Invalid feed parameters. Slug %r is valid, but other parameters, or lack thereof, are not." % slug

View File

@ -149,8 +149,8 @@ DATA_TYPES = {
'NullBooleanField': 'bit', 'NullBooleanField': 'bit',
'OneToOneField': 'int', 'OneToOneField': 'int',
'PhoneNumberField': 'varchar(20)', 'PhoneNumberField': 'varchar(20)',
'PositiveIntegerField': 'int CONSTRAINT [CK_int_pos_%(name)s] CHECK ([%(name)s] > 0)', 'PositiveIntegerField': 'int CONSTRAINT [CK_int_pos_%(column)s] CHECK ([%(column)s] > 0)',
'PositiveSmallIntegerField': 'smallint CONSTRAINT [CK_smallint_pos_%(name)s] CHECK ([%(name)s] > 0)', 'PositiveSmallIntegerField': 'smallint CONSTRAINT [CK_smallint_pos_%(column)s] CHECK ([%(column)s] > 0)',
'SlugField': 'varchar(50)', 'SlugField': 'varchar(50)',
'SmallIntegerField': 'smallint', 'SmallIntegerField': 'smallint',
'TextField': 'text', 'TextField': 'text',

View File

@ -170,8 +170,8 @@ DATA_TYPES = {
'NullBooleanField': 'boolean', 'NullBooleanField': 'boolean',
'OneToOneField': 'integer', 'OneToOneField': 'integer',
'PhoneNumberField': 'varchar(20)', 'PhoneNumberField': 'varchar(20)',
'PositiveIntegerField': 'integer CHECK (%(name)s >= 0)', 'PositiveIntegerField': 'integer CHECK (%(column)s >= 0)',
'PositiveSmallIntegerField': 'smallint CHECK (%(name)s >= 0)', 'PositiveSmallIntegerField': 'smallint CHECK (%(column)s >= 0)',
'SlugField': 'varchar(50)', 'SlugField': 'varchar(50)',
'SmallIntegerField': 'smallint', 'SmallIntegerField': 'smallint',
'TextField': 'text', 'TextField': 'text',

View File

@ -86,14 +86,14 @@ class BaseHandler:
return response return response
except exceptions.Http404, e: except exceptions.Http404, e:
if DEBUG: if DEBUG:
return self.get_technical_error_response(is404=True, exception=e) return self.get_technical_error_response(request, is404=True, exception=e)
else: else:
callback, param_dict = resolver.resolve404() callback, param_dict = resolver.resolve404()
return callback(request, **param_dict) return callback(request, **param_dict)
except db.DatabaseError: except db.DatabaseError:
db.db.rollback() db.db.rollback()
if DEBUG: if DEBUG:
return self.get_technical_error_response() return self.get_technical_error_response(request)
else: else:
subject = 'Database error (%s IP): %s' % ((request.META.get('REMOTE_ADDR') in INTERNAL_IPS and 'internal' or 'EXTERNAL'), getattr(request, 'path', '')) subject = 'Database error (%s IP): %s' % ((request.META.get('REMOTE_ADDR') in INTERNAL_IPS and 'internal' or 'EXTERNAL'), getattr(request, 'path', ''))
message = "%s\n\n%s" % (self._get_traceback(), request) message = "%s\n\n%s" % (self._get_traceback(), request)
@ -103,7 +103,7 @@ class BaseHandler:
return httpwrappers.HttpResponseForbidden('<h1>Permission denied</h1>') return httpwrappers.HttpResponseForbidden('<h1>Permission denied</h1>')
except: # Handle everything else, including SuspiciousOperation, etc. except: # Handle everything else, including SuspiciousOperation, etc.
if DEBUG: if DEBUG:
return self.get_technical_error_response() return self.get_technical_error_response(request)
else: else:
subject = 'Coding error (%s IP): %s' % ((request.META.get('REMOTE_ADDR') in INTERNAL_IPS and 'internal' or 'EXTERNAL'), getattr(request, 'path', '')) subject = 'Coding error (%s IP): %s' % ((request.META.get('REMOTE_ADDR') in INTERNAL_IPS and 'internal' or 'EXTERNAL'), getattr(request, 'path', ''))
try: try:
@ -123,35 +123,17 @@ class BaseHandler:
callback, param_dict = resolver.resolve500() callback, param_dict = resolver.resolve500()
return callback(request, **param_dict) return callback(request, **param_dict)
def get_technical_error_response(self, is404=False, exception=None): def get_technical_error_response(self, request, is404=False, exception=None):
""" """
Returns an HttpResponse that displays a TECHNICAL error message for a Returns an HttpResponse that displays a TECHNICAL error message for a
fundamental database or coding error. fundamental database or coding error.
""" """
import sys
from django.views import debug
if is404: if is404:
from django.conf.settings import ROOT_URLCONF return debug.technical_404_response(request, exception)
from django.utils.html import escape
html = ['<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">']
html.append('<html><head><title>Error 404</title>')
# Explicitly tell robots not to archive this, in case this slips
# onto a production site.
html.append('<meta name="robots" content="NONE,NOARCHIVE" />')
html.append('</head><body><h1>Error 404</h1>')
try:
tried = exception.args[0]['tried']
except (IndexError, TypeError):
if exception.args:
html.append('<p>%s</p>' % escape(exception.args[0]))
else: else:
html.append('<p>Using the URLconf defined in <code>%s</code>, Django tried these URL patterns, in this order:</p>' % ROOT_URLCONF) return debug.technical_500_response(request, *sys.exc_info())
html.append('<ul>%s</ul>' % ''.join(['<li><code>%s</code></li>' % escape(t).replace(' ', '&nbsp;') for t in tried]))
html.append("<p>The current URL, <code><strong>%r</strong></code>, didn't match any of these.</p>" % exception.args[0]['path'])
html.append("<hr /><p>You're seeing this error because you have <code>DEBUG = True</code> in your Django settings file. Change that to <code>False</code>, and Django will display a standard 404 page.</p>")
html.append('</body></html>')
return httpwrappers.HttpResponseNotFound('\n'.join(html))
else:
output = "There's been an error:\n\n%s" % self._get_traceback()
return httpwrappers.HttpResponseServerError(output, mimetype='text/plain')
def _get_traceback(self): def _get_traceback(self):
"Helper function to return the traceback as a string" "Helper function to return the traceback as a string"

View File

@ -19,7 +19,10 @@ APP_ARGS = '[modelmodule ...]'
PROJECT_TEMPLATE_DIR = os.path.join(django.__path__[0], 'conf', '%s_template') PROJECT_TEMPLATE_DIR = os.path.join(django.__path__[0], 'conf', '%s_template')
def _get_packages_insert(app_label): def _get_packages_insert(app_label):
return "INSERT INTO packages (label, name) VALUES ('%s', '%s');" % (app_label, app_label) from django.core.db import db
return "INSERT INTO %s (%s, %s) VALUES ('%s', '%s');" % \
(db.quote_name('packages'), db.quote_name('label'), db.quote_name('name'),
app_label, app_label)
def _get_permission_codename(action, opts): def _get_permission_codename(action, opts):
return '%s_%s' % (action, opts.object_name.lower()) return '%s_%s' % (action, opts.object_name.lower())
@ -33,12 +36,16 @@ def _get_all_permissions(opts):
return perms + list(opts.permissions) return perms + list(opts.permissions)
def _get_permission_insert(name, codename, opts): def _get_permission_insert(name, codename, opts):
return "INSERT INTO auth_permissions (name, package, codename) VALUES ('%s', '%s', '%s');" % \ from django.core.db import db
(name.replace("'", "''"), opts.app_label, codename) return "INSERT INTO %s (%s, %s, %s) VALUES ('%s', '%s', '%s');" % \
(db.quote_name('auth_permissions'), db.quote_name('name'), db.quote_name('package'),
db.quote_name('codename'), name.replace("'", "''"), opts.app_label, codename)
def _get_contenttype_insert(opts): def _get_contenttype_insert(opts):
return "INSERT INTO content_types (name, package, python_module_name) VALUES ('%s', '%s', '%s');" % \ from django.core.db import db
(opts.verbose_name, opts.app_label, opts.module_name) return "INSERT INTO %s (%s, %s, %s) VALUES ('%s', '%s', '%s');" % \
(db.quote_name('content_types'), db.quote_name('name'), db.quote_name('package'),
db.quote_name('python_module_name'), opts.verbose_name, opts.app_label, opts.module_name)
def _is_valid_dir_name(s): def _is_valid_dir_name(s):
return bool(re.search(r'^\w+$', s)) return bool(re.search(r'^\w+$', s))
@ -64,7 +71,7 @@ def get_sql_create(mod):
data_type = f.get_internal_type() data_type = f.get_internal_type()
col_type = db.DATA_TYPES[data_type] col_type = db.DATA_TYPES[data_type]
if col_type is not None: if col_type is not None:
field_output = [f.column, col_type % rel_field.__dict__] field_output = [db.db.quote_name(f.column), col_type % rel_field.__dict__]
field_output.append('%sNULL' % (not f.null and 'NOT ' or '')) field_output.append('%sNULL' % (not f.null and 'NOT ' or ''))
if f.unique: if f.unique:
field_output.append('UNIQUE') field_output.append('UNIQUE')
@ -72,14 +79,16 @@ def get_sql_create(mod):
field_output.append('PRIMARY KEY') field_output.append('PRIMARY KEY')
if f.rel: if f.rel:
field_output.append('REFERENCES %s (%s)' % \ field_output.append('REFERENCES %s (%s)' % \
(f.rel.to.db_table, f.rel.to.get_field(f.rel.field_name).column)) (db.db.quote_name(f.rel.to.db_table),
db.db.quote_name(f.rel.to.get_field(f.rel.field_name).column)))
table_output.append(' '.join(field_output)) table_output.append(' '.join(field_output))
if opts.order_with_respect_to: if opts.order_with_respect_to:
table_output.append('_order %s NULL' % db.DATA_TYPES['IntegerField']) table_output.append('%s %s NULL' % (db.db.quote_name('_order'), db.DATA_TYPES['IntegerField']))
for field_constraints in opts.unique_together: for field_constraints in opts.unique_together:
table_output.append('UNIQUE (%s)' % ", ".join([opts.get_field(f).column for f in field_constraints])) table_output.append('UNIQUE (%s)' % \
", ".join([db.db.quote_name(opts.get_field(f).column) for f in field_constraints]))
full_statement = ['CREATE TABLE %s (' % opts.db_table] full_statement = ['CREATE TABLE %s (' % db.db.quote_name(opts.db_table)]
for i, line in enumerate(table_output): # Combine and add commas. for i, line in enumerate(table_output): # Combine and add commas.
full_statement.append(' %s%s' % (line, i < len(table_output)-1 and ',' or '')) full_statement.append(' %s%s' % (line, i < len(table_output)-1 and ',' or ''))
full_statement.append(');') full_statement.append(');')
@ -88,13 +97,21 @@ def get_sql_create(mod):
for klass in mod._MODELS: for klass in mod._MODELS:
opts = klass._meta opts = klass._meta
for f in opts.many_to_many: for f in opts.many_to_many:
table_output = ['CREATE TABLE %s (' % f.get_m2m_db_table(opts)] table_output = ['CREATE TABLE %s (' % db.db.quote_name(f.get_m2m_db_table(opts))]
table_output.append(' id %s NOT NULL PRIMARY KEY,' % db.DATA_TYPES['AutoField']) table_output.append(' %s %s NOT NULL PRIMARY KEY,' % (db.db.quote_name('id'), db.DATA_TYPES['AutoField']))
table_output.append(' %s_id %s NOT NULL REFERENCES %s (%s),' % \ table_output.append(' %s %s NOT NULL REFERENCES %s (%s),' % \
(opts.object_name.lower(), db.DATA_TYPES[get_rel_data_type(opts.pk)] % opts.pk.__dict__, opts.db_table, opts.pk.column)) (db.db.quote_name(opts.object_name.lower() + '_id'),
table_output.append(' %s_id %s NOT NULL REFERENCES %s (%s),' % \ db.DATA_TYPES[get_rel_data_type(opts.pk)] % opts.pk.__dict__,
(f.rel.to.object_name.lower(), db.DATA_TYPES[get_rel_data_type(f.rel.to.pk)] % f.rel.to.pk.__dict__, f.rel.to.db_table, f.rel.to.pk.column)) db.db.quote_name(opts.db_table),
table_output.append(' UNIQUE (%s_id, %s_id)' % (opts.object_name.lower(), f.rel.to.object_name.lower())) db.db.quote_name(opts.pk.column)))
table_output.append(' %s %s NOT NULL REFERENCES %s (%s),' % \
(db.db.quote_name(f.rel.to.object_name.lower() + '_id'),
db.DATA_TYPES[get_rel_data_type(f.rel.to.pk)] % f.rel.to.pk.__dict__,
db.db.quote_name(f.rel.to.db_table),
db.db.quote_name(f.rel.to.pk.column)))
table_output.append(' UNIQUE (%s, %s)' % \
(db.db.quote_name(opts.object_name.lower() + '_id'),
db.db.quote_name(f.rel.to.object_name.lower() + '_id')))
table_output.append(');') table_output.append(');')
final_output.append('\n'.join(table_output)) final_output.append('\n'.join(table_output))
return final_output return final_output
@ -114,7 +131,7 @@ def get_sql_delete(mod):
try: try:
if cursor is not None: if cursor is not None:
# Check whether the table exists. # Check whether the table exists.
cursor.execute("SELECT 1 FROM django_admin_log LIMIT 1") cursor.execute("SELECT 1 FROM %s LIMIT 1" % db.db.quote_name('django_admin_log'))
except: except:
# The table doesn't exist, so it doesn't need to be dropped. # The table doesn't exist, so it doesn't need to be dropped.
db.db.rollback() db.db.rollback()
@ -129,12 +146,12 @@ def get_sql_delete(mod):
try: try:
if cursor is not None: if cursor is not None:
# Check whether the table exists. # Check whether the table exists.
cursor.execute("SELECT 1 FROM %s LIMIT 1" % klass._meta.db_table) cursor.execute("SELECT 1 FROM %s LIMIT 1" % db.db.quote_name(klass._meta.db_table))
except: except:
# The table doesn't exist, so it doesn't need to be dropped. # The table doesn't exist, so it doesn't need to be dropped.
db.db.rollback() db.db.rollback()
else: else:
output.append("DROP TABLE %s;" % klass._meta.db_table) output.append("DROP TABLE %s;" % db.db.quote_name(klass._meta.db_table))
# Output DROP TABLE statements for many-to-many tables. # Output DROP TABLE statements for many-to-many tables.
for klass in mod._MODELS: for klass in mod._MODELS:
@ -142,25 +159,31 @@ def get_sql_delete(mod):
for f in opts.many_to_many: for f in opts.many_to_many:
try: try:
if cursor is not None: if cursor is not None:
cursor.execute("SELECT 1 FROM %s LIMIT 1" % f.get_m2m_db_table(opts)) cursor.execute("SELECT 1 FROM %s LIMIT 1" % db.db.quote_name(f.get_m2m_db_table(opts)))
except: except:
db.db.rollback() db.db.rollback()
else: else:
output.append("DROP TABLE %s;" % f.get_m2m_db_table(opts)) output.append("DROP TABLE %s;" % db.db.quote_name(f.get_m2m_db_table(opts)))
app_label = mod._MODELS[0]._meta.app_label app_label = mod._MODELS[0]._meta.app_label
# Delete from packages, auth_permissions, content_types. # Delete from packages, auth_permissions, content_types.
output.append("DELETE FROM packages WHERE label = '%s';" % app_label) output.append("DELETE FROM %s WHERE %s = '%s';" % \
output.append("DELETE FROM auth_permissions WHERE package = '%s';" % app_label) (db.db.quote_name('packages'), db.db.quote_name('label'), app_label))
output.append("DELETE FROM content_types WHERE package = '%s';" % app_label) output.append("DELETE FROM %s WHERE %s = '%s';" % \
(db.db.quote_name('auth_permissions'), db.db.quote_name('package'), app_label))
output.append("DELETE FROM %s WHERE %s = '%s';" % \
(db.db.quote_name('content_types'), db.db.quote_name('package'), app_label))
# Delete from the admin log. # Delete from the admin log.
if cursor is not None: if cursor is not None:
cursor.execute("SELECT id FROM content_types WHERE package = %s", [app_label]) cursor.execute("SELECT %s FROM %s WHERE %s = %%s" % \
(db.db.quote_name('id'), db.db.quote_name('content_types'),
db.db.quote_name('package')), [app_label])
if admin_log_exists: if admin_log_exists:
for row in cursor.fetchall(): for row in cursor.fetchall():
output.append("DELETE FROM django_admin_log WHERE content_type_id = %s;" % row[0]) output.append("DELETE FROM %s WHERE %s = %s;" % \
(db.db.quote_name('django_admin_log'), db.db.quote_name('content_type_id'), row[0]))
# Close database connection explicitly, in case this output is being piped # Close database connection explicitly, in case this output is being piped
# directly into a database client, to avoid locking issues. # directly into a database client, to avoid locking issues.
@ -206,25 +229,29 @@ get_sql_initial_data.args = APP_ARGS
def get_sql_sequence_reset(mod): def get_sql_sequence_reset(mod):
"Returns a list of the SQL statements to reset PostgreSQL sequences for the given module." "Returns a list of the SQL statements to reset PostgreSQL sequences for the given module."
from django.core import meta from django.core import db, meta
output = [] output = []
for klass in mod._MODELS: for klass in mod._MODELS:
for f in klass._meta.fields: for f in klass._meta.fields:
if isinstance(f, meta.AutoField): if isinstance(f, meta.AutoField):
output.append("SELECT setval('%s_%s_seq', (SELECT max(%s) FROM %s));" % (klass._meta.db_table, f.column, f.column, klass._meta.db_table)) output.append("SELECT setval('%s_%s_seq', (SELECT max(%s) FROM %s));" % \
(klass._meta.db_table, f.column, db.db.quote_name(f.column),
db.db.quote_name(klass._meta.db_table)))
return output return output
get_sql_sequence_reset.help_doc = "Prints the SQL statements for resetting PostgreSQL sequences for the given model module name(s)." get_sql_sequence_reset.help_doc = "Prints the SQL statements for resetting PostgreSQL sequences for the given model module name(s)."
get_sql_sequence_reset.args = APP_ARGS get_sql_sequence_reset.args = APP_ARGS
def get_sql_indexes(mod): def get_sql_indexes(mod):
"Returns a list of the CREATE INDEX SQL statements for the given module." "Returns a list of the CREATE INDEX SQL statements for the given module."
from django.core.db import db
output = [] output = []
for klass in mod._MODELS: for klass in mod._MODELS:
for f in klass._meta.fields: for f in klass._meta.fields:
if f.db_index: if f.db_index:
unique = f.unique and "UNIQUE " or "" unique = f.unique and "UNIQUE " or ""
output.append("CREATE %sINDEX %s_%s ON %s (%s);" % \ output.append("CREATE %sINDEX %s_%s ON %s (%s);" % \
(unique, klass._meta.db_table, f.column, klass._meta.db_table, f.column)) (unique, klass._meta.db_table, f.column,
db.quote_name(klass._meta.db_table), db.quote_name(f.column)))
return output return output
get_sql_indexes.help_doc = "Prints the CREATE INDEX SQL statements for the given model module name(s)." get_sql_indexes.help_doc = "Prints the CREATE INDEX SQL statements for the given model module name(s)."
get_sql_indexes.args = APP_ARGS get_sql_indexes.args = APP_ARGS
@ -242,7 +269,8 @@ def database_check(mod):
app_label = mod._MODELS[0]._meta.app_label app_label = mod._MODELS[0]._meta.app_label
# Check that the package exists in the database. # Check that the package exists in the database.
cursor.execute("SELECT 1 FROM packages WHERE label = %s", [app_label]) cursor.execute("SELECT 1 FROM %s WHERE %s = %%s" % \
(db.db.quote_name('packages'), db.db.quote_name('label')), [app_label])
if cursor.rowcount < 1: if cursor.rowcount < 1:
# sys.stderr.write("The '%s' package isn't installed.\n" % app_label) # sys.stderr.write("The '%s' package isn't installed.\n" % app_label)
print _get_packages_insert(app_label) print _get_packages_insert(app_label)
@ -256,34 +284,46 @@ def database_check(mod):
perms_seen.update(dict(perms)) perms_seen.update(dict(perms))
contenttypes_seen[opts.module_name] = 1 contenttypes_seen[opts.module_name] = 1
for codename, name in perms: for codename, name in perms:
cursor.execute("SELECT 1 FROM auth_permissions WHERE package = %s AND codename = %s", (app_label, codename)) cursor.execute("SELECT 1 FROM %s WHERE %s = %%s AND %s = %%s" % \
(db.db.quote_name('auth_permissions'), db.db.quote_name('package'),
db.db.quote_name('codename')), (app_label, codename))
if cursor.rowcount < 1: if cursor.rowcount < 1:
# sys.stderr.write("The '%s.%s' permission doesn't exist.\n" % (app_label, codename)) # sys.stderr.write("The '%s.%s' permission doesn't exist.\n" % (app_label, codename))
print _get_permission_insert(name, codename, opts) print _get_permission_insert(name, codename, opts)
cursor.execute("SELECT 1 FROM content_types WHERE package = %s AND python_module_name = %s", (app_label, opts.module_name)) cursor.execute("SELECT 1 FROM %s WHERE %s = %%s AND %s = %%s" % \
(db.db.quote_name('content_types'), db.db.quote_name('package'),
db.db.quote_name('python_module_name')), (app_label, opts.module_name))
if cursor.rowcount < 1: if cursor.rowcount < 1:
# sys.stderr.write("The '%s.%s' content type doesn't exist.\n" % (app_label, opts.module_name)) # sys.stderr.write("The '%s.%s' content type doesn't exist.\n" % (app_label, opts.module_name))
print _get_contenttype_insert(opts) print _get_contenttype_insert(opts)
# Check that there aren't any *extra* permissions in the DB that the model # Check that there aren't any *extra* permissions in the DB that the model
# doesn't know about. # doesn't know about.
cursor.execute("SELECT codename FROM auth_permissions WHERE package = %s", (app_label,)) cursor.execute("SELECT %s FROM %s WHERE %s = %%s" % \
(db.db.quote_name('codename'), db.db.quote_name('auth_permissions'),
db.db.quote_name('package')), (app_label,))
for row in cursor.fetchall(): for row in cursor.fetchall():
try: try:
perms_seen[row[0]] perms_seen[row[0]]
except KeyError: except KeyError:
# sys.stderr.write("A permission called '%s.%s' was found in the database but not in the model.\n" % (app_label, row[0])) # sys.stderr.write("A permission called '%s.%s' was found in the database but not in the model.\n" % (app_label, row[0]))
print "DELETE FROM auth_permissions WHERE package='%s' AND codename = '%s';" % (app_label, row[0]) print "DELETE FROM %s WHERE %s='%s' AND %s = '%s';" % \
(db.db.quote_name('auth_permissions'), db.db.quote_name('package'),
app_label, db.db.quote_name('codename'), row[0])
# Check that there aren't any *extra* content types in the DB that the # Check that there aren't any *extra* content types in the DB that the
# model doesn't know about. # model doesn't know about.
cursor.execute("SELECT python_module_name FROM content_types WHERE package = %s", (app_label,)) cursor.execute("SELECT %s FROM %s WHERE %s = %%s" % \
(db.db.quote_name('python_module_name'), db.db.quote_name('content_types'),
db.db.quote_name('package')), (app_label,))
for row in cursor.fetchall(): for row in cursor.fetchall():
try: try:
contenttypes_seen[row[0]] contenttypes_seen[row[0]]
except KeyError: except KeyError:
# sys.stderr.write("A content type called '%s.%s' was found in the database but not in the model.\n" % (app_label, row[0])) # sys.stderr.write("A content type called '%s.%s' was found in the database but not in the model.\n" % (app_label, row[0]))
print "DELETE FROM content_types WHERE package='%s' AND python_module_name = '%s';" % (app_label, row[0]) print "DELETE FROM %s WHERE %s='%s' AND %s = '%s';" % \
(db.db.quote_name('content_types'), db.db.quote_name('package'),
app_label, db.db.quote_name('python_module_name'), row[0])
database_check.help_doc = "Checks that everything is installed in the database for the given model module name(s) and prints SQL statements if needed." database_check.help_doc = "Checks that everything is installed in the database for the given model module name(s) and prints SQL statements if needed."
database_check.args = APP_ARGS database_check.args = APP_ARGS
@ -318,7 +358,9 @@ def init():
cursor = db.db.cursor() cursor = db.db.cursor()
for sql in get_sql_create(core) + get_sql_create(auth) + get_sql_initial_data(core) + get_sql_initial_data(auth): for sql in get_sql_create(core) + get_sql_create(auth) + get_sql_initial_data(core) + get_sql_initial_data(auth):
cursor.execute(sql) cursor.execute(sql)
cursor.execute("INSERT INTO %s (domain, name) VALUES ('example.com', 'Example site')" % core.Site._meta.db_table) cursor.execute("INSERT INTO %s (%s, %s) VALUES ('example.com', 'Example site')" % \
(db.db.quote_name(core.Site._meta.db_table), db.db.quote_name('domain'),
db.db.quote_name('name')))
except Exception, e: except Exception, e:
sys.stderr.write("Error: The database couldn't be initialized.\n%s\n" % e) sys.stderr.write("Error: The database couldn't be initialized.\n%s\n" % e)
try: try:
@ -687,7 +729,7 @@ def createcachetable(tablename):
table_output = [] table_output = []
index_output = [] index_output = []
for f in fields: for f in fields:
field_output = [f.column, db.DATA_TYPES[f.get_internal_type()] % f.__dict__] field_output = [db.db.quote_name(f.column), db.DATA_TYPES[f.get_internal_type()] % f.__dict__]
field_output.append("%sNULL" % (not f.null and "NOT " or "")) field_output.append("%sNULL" % (not f.null and "NOT " or ""))
if f.unique: if f.unique:
field_output.append("UNIQUE") field_output.append("UNIQUE")
@ -695,9 +737,11 @@ def createcachetable(tablename):
field_output.append("PRIMARY KEY") field_output.append("PRIMARY KEY")
if f.db_index: if f.db_index:
unique = f.unique and "UNIQUE " or "" unique = f.unique and "UNIQUE " or ""
index_output.append("CREATE %sINDEX %s_%s ON %s (%s);" % (unique, tablename, f.column, tablename, f.column)) index_output.append("CREATE %sINDEX %s_%s ON %s (%s);" % \
(unique, tablename, f.column, db.db.quote_name(tablename),
db.db.quote_name(f.column)))
table_output.append(" ".join(field_output)) table_output.append(" ".join(field_output))
full_statement = ["CREATE TABLE %s (" % tablename] full_statement = ["CREATE TABLE %s (" % db.db.quote_name(tablename)]
for i, line in enumerate(table_output): for i, line in enumerate(table_output):
full_statement.append(' %s%s' % (line, i < len(table_output)-1 and ',' or '')) full_statement.append(' %s%s' % (line, i < len(table_output)-1 and ',' or ''))
full_statement.append(');') full_statement.append(');')

View File

@ -57,14 +57,16 @@ def orderfield2column(f, opts):
return f return f
def orderlist2sql(order_list, opts, prefix=''): def orderlist2sql(order_list, opts, prefix=''):
if prefix.endswith('.'):
prefix = db.db.quote_name(prefix[:-1]) + '.'
output = [] output = []
for f in handle_legacy_orderlist(order_list): for f in handle_legacy_orderlist(order_list):
if f.startswith('-'): if f.startswith('-'):
output.append('%s%s DESC' % (prefix, orderfield2column(f[1:], opts))) output.append('%s%s DESC' % (prefix, db.db.quote_name(orderfield2column(f[1:], opts))))
elif f == '?': elif f == '?':
output.append(db.get_random_function_sql()) output.append(db.get_random_function_sql())
else: else:
output.append('%s%s ASC' % (prefix, orderfield2column(f, opts))) output.append('%s%s ASC' % (prefix, db.db.quote_name(orderfield2column(f, opts))))
return ', '.join(output) return ', '.join(output)
def get_module(app_label, module_name): def get_module(app_label, module_name):
@ -923,27 +925,31 @@ def method_save(opts, self):
record_exists = True record_exists = True
if pk_set: if pk_set:
# Determine whether a record with the primary key already exists. # Determine whether a record with the primary key already exists.
cursor.execute("SELECT 1 FROM %s WHERE %s=%%s LIMIT 1" % (opts.db_table, opts.pk.column), [pk_val]) cursor.execute("SELECT 1 FROM %s WHERE %s=%%s LIMIT 1" % \
(db.db.quote_name(opts.db_table), db.db.quote_name(opts.pk.column)), [pk_val])
# If it does already exist, do an UPDATE. # If it does already exist, do an UPDATE.
if cursor.fetchone(): if cursor.fetchone():
db_values = [f.get_db_prep_save(f.pre_save(getattr(self, f.attname), False)) for f in non_pks] db_values = [f.get_db_prep_save(f.pre_save(getattr(self, f.attname), False)) for f in non_pks]
cursor.execute("UPDATE %s SET %s WHERE %s=%%s" % (opts.db_table, cursor.execute("UPDATE %s SET %s WHERE %s=%%s" % \
','.join(['%s=%%s' % f.column for f in non_pks]), opts.pk.attname), (db.db.quote_name(opts.db_table),
','.join(['%s=%%s' % db.db.quote_name(f.column) for f in non_pks]),
db.db.quote_name(opts.pk.attname)),
db_values + [pk_val]) db_values + [pk_val])
else: else:
record_exists = False record_exists = False
if not pk_set or not record_exists: if not pk_set or not record_exists:
field_names = [f.column for f in opts.fields if not isinstance(f, AutoField)] field_names = [db.db.quote_name(f.column) for f in opts.fields if not isinstance(f, AutoField)]
placeholders = ['%s'] * len(field_names) placeholders = ['%s'] * len(field_names)
db_values = [f.get_db_prep_save(f.pre_save(getattr(self, f.attname), True)) for f in opts.fields if not isinstance(f, AutoField)] db_values = [f.get_db_prep_save(f.pre_save(getattr(self, f.attname), True)) for f in opts.fields if not isinstance(f, AutoField)]
if opts.order_with_respect_to: if opts.order_with_respect_to:
field_names.append('_order') field_names.append(db.db.quote_name('_order'))
# TODO: This assumes the database supports subqueries. # TODO: This assumes the database supports subqueries.
placeholders.append('(SELECT COUNT(*) FROM %s WHERE %s = %%s)' % \ placeholders.append('(SELECT COUNT(*) FROM %s WHERE %s = %%s)' % \
(opts.db_table, opts.order_with_respect_to.column)) (db.db.quote_name(opts.db_table), db.db.quote_name(opts.order_with_respect_to.column)))
db_values.append(getattr(self, opts.order_with_respect_to.attname)) db_values.append(getattr(self, opts.order_with_respect_to.attname))
cursor.execute("INSERT INTO %s (%s) VALUES (%s)" % (opts.db_table, cursor.execute("INSERT INTO %s (%s) VALUES (%s)" % \
','.join(field_names), ','.join(placeholders)), db_values) (db.db.quote_name(opts.db_table), ','.join(field_names),
','.join(placeholders)), db_values)
if opts.has_auto_field: if opts.has_auto_field:
setattr(self, opts.pk.attname, db.get_last_insert_id(cursor, opts.db_table, opts.pk.column)) setattr(self, opts.pk.attname, db.get_last_insert_id(cursor, opts.db_table, opts.pk.column))
db.db.commit() db.db.commit()
@ -970,12 +976,17 @@ def method_delete(opts, self):
for sub_obj in getattr(self, 'get_%s_list' % rel_opts_name)(): for sub_obj in getattr(self, 'get_%s_list' % rel_opts_name)():
sub_obj.delete() sub_obj.delete()
for related in opts.get_all_related_many_to_many_objects(): for related in opts.get_all_related_many_to_many_objects():
cursor.execute("DELETE FROM %s WHERE %s_id=%%s" % (related.field.get_m2m_db_table(related.opts), cursor.execute("DELETE FROM %s WHERE %s=%%s" % \
self._meta.object_name.lower()), [getattr(self, opts.pk.attname)]) (db.db.quote_name(related.field.get_m2m_db_table(related.opts)),
db.db.quote_name(self._meta.object_name.lower() + '_id')), [getattr(self, opts.pk.attname)])
for f in opts.many_to_many: for f in opts.many_to_many:
cursor.execute("DELETE FROM %s WHERE %s_id=%%s" % (f.get_m2m_db_table(opts), self._meta.object_name.lower()), cursor.execute("DELETE FROM %s WHERE %s=%%s" % \
(db.db.quote_name(f.get_m2m_db_table(opts)),
db.db.quote_name(self._meta.object_name.lower() + '_id')),
[getattr(self, opts.pk.attname)])
cursor.execute("DELETE FROM %s WHERE %s=%%s" % \
(db.db.quote_name(opts.db_table), db.db.quote_name(opts.pk.column)),
[getattr(self, opts.pk.attname)]) [getattr(self, opts.pk.attname)])
cursor.execute("DELETE FROM %s WHERE %s=%%s" % (opts.db_table, opts.pk.column), [getattr(self, opts.pk.attname)])
db.db.commit() db.db.commit()
setattr(self, opts.pk.attname, None) setattr(self, opts.pk.attname, None)
for f in opts.fields: for f in opts.fields:
@ -992,16 +1003,20 @@ def method_delete(opts, self):
def method_get_next_in_order(opts, order_field, self): def method_get_next_in_order(opts, order_field, self):
if not hasattr(self, '_next_in_order_cache'): if not hasattr(self, '_next_in_order_cache'):
self._next_in_order_cache = opts.get_model_module().get_object(order_by=('_order',), self._next_in_order_cache = opts.get_model_module().get_object(order_by=('_order',),
where=['_order > (SELECT _order FROM %s WHERE %s=%%s)' % (opts.db_table, opts.pk.column), where=['%s > (SELECT %s FROM %s WHERE %s=%%s)' % \
'%s=%%s' % order_field.column], limit=1, (db.db.quote_name('_order'), db.db.quote_name('_order'),
db.db.quote_name(opts.db_table), db.db.quote_name(opts.pk.column)),
'%s=%%s' % db.db.quote_name(order_field.column)], limit=1,
params=[getattr(self, opts.pk.attname), getattr(self, order_field.attname)]) params=[getattr(self, opts.pk.attname), getattr(self, order_field.attname)])
return self._next_in_order_cache return self._next_in_order_cache
def method_get_previous_in_order(opts, order_field, self): def method_get_previous_in_order(opts, order_field, self):
if not hasattr(self, '_previous_in_order_cache'): if not hasattr(self, '_previous_in_order_cache'):
self._previous_in_order_cache = opts.get_model_module().get_object(order_by=('-_order',), self._previous_in_order_cache = opts.get_model_module().get_object(order_by=('-_order',),
where=['_order < (SELECT _order FROM %s WHERE %s=%%s)' % (opts.db_table, opts.pk.column), where=['%s < (SELECT %s FROM %s WHERE %s=%%s)' % \
'%s=%%s' % order_field.column], limit=1, (db.db.quote_name('_order'), db.db.quote_name('_order'),
db.db.quote_name(opts.db_table), db.db.quote_name(opts.pk.column)),
'%s=%%s' % db.db.quote_name(order_field.column)], limit=1,
params=[getattr(self, opts.pk.attname), getattr(self, order_field.attname)]) params=[getattr(self, opts.pk.attname), getattr(self, order_field.attname)])
return self._previous_in_order_cache return self._previous_in_order_cache
@ -1026,10 +1041,13 @@ def method_get_many_to_many(field_with_rel, self):
cache_var = '_%s_cache' % field_with_rel.name cache_var = '_%s_cache' % field_with_rel.name
if not hasattr(self, cache_var): if not hasattr(self, cache_var):
mod = rel.get_model_module() mod = rel.get_model_module()
sql = "SELECT %s FROM %s a, %s b WHERE a.%s = b.%s_id AND b.%s_id = %%s %s" % \ sql = "SELECT %s FROM %s a, %s b WHERE a.%s = b.%s AND b.%s = %%s %s" % \
(','.join(['a.%s' % f.column for f in rel.fields]), rel.db_table, (','.join(['a.%s' % db.db.quote_name(f.column) for f in rel.fields]),
field_with_rel.get_m2m_db_table(self._meta), rel.pk.column, db.db.quote_name(rel.db_table),
rel.object_name.lower(), self._meta.object_name.lower(), rel.get_order_sql('a')) db.db.quote_name(field_with_rel.get_m2m_db_table(self._meta)),
db.db.quote_name(rel.pk.column),
db.db.quote_name(rel.object_name.lower() + '_id'),
db.db.quote_name(self._meta.object_name.lower() + '_id'), rel.get_order_sql('a'))
cursor = db.db.cursor() cursor = db.db.cursor()
cursor.execute(sql, [getattr(self, self._meta.pk.attname)]) cursor.execute(sql, [getattr(self, self._meta.pk.attname)])
setattr(self, cache_var, [getattr(mod, rel.object_name)(*row) for row in cursor.fetchall()]) setattr(self, cache_var, [getattr(mod, rel.object_name)(*row) for row in cursor.fetchall()])
@ -1054,10 +1072,16 @@ def method_set_many_to_many(rel_field, self, id_list):
cursor = db.db.cursor() cursor = db.db.cursor()
this_id = getattr(self, self._meta.pk.attname) this_id = getattr(self, self._meta.pk.attname)
if ids_to_delete: if ids_to_delete:
sql = "DELETE FROM %s WHERE %s_id = %%s AND %s_id IN (%s)" % (m2m_table, self._meta.object_name.lower(), rel.object_name.lower(), ','.join(map(str, ids_to_delete))) sql = "DELETE FROM %s WHERE %s = %%s AND %s IN (%s)" % \
(db.db.quote_name(m2m_table),
db.db.quote_name(self._meta.object_name.lower() + '_id'),
db.db.quote_name(rel.object_name.lower() + '_id'), ','.join(map(str, ids_to_delete)))
cursor.execute(sql, [this_id]) cursor.execute(sql, [this_id])
if ids_to_add: if ids_to_add:
sql = "INSERT INTO %s (%s_id, %s_id) VALUES (%%s, %%s)" % (m2m_table, self._meta.object_name.lower(), rel.object_name.lower()) sql = "INSERT INTO %s (%s, %s) VALUES (%%s, %%s)" % \
(db.db.quote_name(m2m_table),
db.db.quote_name(self._meta.object_name.lower() + '_id'),
db.db.quote_name(rel.object_name.lower() + '_id'))
cursor.executemany(sql, [(this_id, i) for i in ids_to_add]) cursor.executemany(sql, [(this_id, i) for i in ids_to_add])
db.db.commit() db.db.commit()
try: try:
@ -1103,8 +1127,13 @@ def method_set_related_many_to_many(rel_opts, rel_field, self, id_list):
m2m_table = rel_field.get_m2m_db_table(rel_opts) m2m_table = rel_field.get_m2m_db_table(rel_opts)
this_id = getattr(self, self._meta.pk.attname) this_id = getattr(self, self._meta.pk.attname)
cursor = db.db.cursor() cursor = db.db.cursor()
cursor.execute("DELETE FROM %s WHERE %s_id = %%s" % (m2m_table, rel.object_name.lower()), [this_id]) cursor.execute("DELETE FROM %s WHERE %s = %%s" % \
sql = "INSERT INTO %s (%s_id, %s_id) VALUES (%%s, %%s)" % (m2m_table, rel.object_name.lower(), rel_opts.object_name.lower()) (db.db.quote_name(m2m_table),
db.db.quote_name(rel.object_name.lower() + '_id')), [this_id])
sql = "INSERT INTO %s (%s, %s) VALUES (%%s, %%s)" % \
(db.db.quote_name(m2m_table),
db.db.quote_name(rel.object_name.lower() + '_id'),
db.db.quote_name(rel_opts.object_name.lower() + '_id'))
cursor.executemany(sql, [(this_id, i) for i in id_list]) cursor.executemany(sql, [(this_id, i) for i in id_list])
db.db.commit() db.db.commit()
@ -1113,7 +1142,10 @@ def method_set_related_many_to_many(rel_opts, rel_field, self, id_list):
def method_set_order(ordered_obj, self, id_list): def method_set_order(ordered_obj, self, id_list):
cursor = db.db.cursor() cursor = db.db.cursor()
# Example: "UPDATE poll_choices SET _order = %s WHERE poll_id = %s AND id = %s" # Example: "UPDATE poll_choices SET _order = %s WHERE poll_id = %s AND id = %s"
sql = "UPDATE %s SET _order = %%s WHERE %s = %%s AND %s = %%s" % (ordered_obj.db_table, ordered_obj.order_with_respect_to.column, ordered_obj.pk.column) sql = "UPDATE %s SET %s = %%s WHERE %s = %%s AND %s = %%s" % \
(db.db.quote_name(ordered_obj.db_table), db.db.quote_name('_order'),
db.db.quote_name(ordered_obj.order_with_respect_to.column),
db.db.quote_name(ordered_obj.pk.column))
rel_val = getattr(self, ordered_obj.order_with_respect_to.rel.field_name) rel_val = getattr(self, ordered_obj.order_with_respect_to.rel.field_name)
cursor.executemany(sql, [(i, rel_val, j) for i, j in enumerate(id_list)]) cursor.executemany(sql, [(i, rel_val, j) for i, j in enumerate(id_list)])
db.db.commit() db.db.commit()
@ -1121,7 +1153,11 @@ def method_set_order(ordered_obj, self, id_list):
def method_get_order(ordered_obj, self): def method_get_order(ordered_obj, self):
cursor = db.db.cursor() cursor = db.db.cursor()
# Example: "SELECT id FROM poll_choices WHERE poll_id = %s ORDER BY _order" # Example: "SELECT id FROM poll_choices WHERE poll_id = %s ORDER BY _order"
sql = "SELECT %s FROM %s WHERE %s = %%s ORDER BY _order" % (ordered_obj.pk.column, ordered_obj.db_table, ordered_obj.order_with_respect_to.column) sql = "SELECT %s FROM %s WHERE %s = %%s ORDER BY %s" % \
(db.db.quote_name(ordered_obj.pk.column),
db.db.quote_name(ordered_obj.db_table),
db.db.quote_name(ordered_obj.order_with_respect_to.column),
db.db.quote_name('_order'))
rel_val = getattr(self, ordered_obj.order_with_respect_to.rel.field_name) rel_val = getattr(self, ordered_obj.order_with_respect_to.rel.field_name)
cursor.execute(sql, [rel_val]) cursor.execute(sql, [rel_val])
return [r[0] for r in cursor.fetchall()] return [r[0] for r in cursor.fetchall()]
@ -1131,7 +1167,8 @@ def method_get_order(ordered_obj, self):
def method_get_next_or_previous(get_object_func, opts, field, is_next, self, **kwargs): def method_get_next_or_previous(get_object_func, opts, field, is_next, self, **kwargs):
op = is_next and '>' or '<' op = is_next and '>' or '<'
kwargs.setdefault('where', []).append('(%s %s %%s OR (%s = %%s AND %s %s %%s))' % \ kwargs.setdefault('where', []).append('(%s %s %%s OR (%s = %%s AND %s %s %%s))' % \
(field.column, op, field.column, opts.pk.column, op)) (db.db.quote_name(field.column), op, db.db.quote_name(field.column),
db.db.quote_name(opts.pk.column), op))
param = str(getattr(self, field.attname)) param = str(getattr(self, field.attname))
kwargs.setdefault('params', []).extend([param, param, getattr(self, opts.pk.attname)]) kwargs.setdefault('params', []).extend([param, param, getattr(self, opts.pk.attname)])
kwargs['order_by'] = [(not is_next and '-' or '') + field.name, (not is_next and '-' or '') + opts.pk.name] kwargs['order_by'] = [(not is_next and '-' or '') + field.name, (not is_next and '-' or '') + opts.pk.name]
@ -1218,6 +1255,9 @@ def get_absolute_url(opts, func, self):
return settings.ABSOLUTE_URL_OVERRIDES.get('%s.%s' % (opts.app_label, opts.module_name), func)(self) return settings.ABSOLUTE_URL_OVERRIDES.get('%s.%s' % (opts.app_label, opts.module_name), func)(self)
def _get_where_clause(lookup_type, table_prefix, field_name, value): def _get_where_clause(lookup_type, table_prefix, field_name, value):
if table_prefix.endswith('.'):
table_prefix = db.db.quote_name(table_prefix[:-1])+'.'
field_name = db.db.quote_name(field_name)
try: try:
return '%s%s %s %%s' % (table_prefix, field_name, db.OPERATOR_MAPPING[lookup_type]) return '%s%s %s %%s' % (table_prefix, field_name, db.OPERATOR_MAPPING[lookup_type])
except KeyError: except KeyError:
@ -1298,7 +1338,7 @@ def function_get_values_iterator(opts, klass, **kwargs):
cursor = db.db.cursor() cursor = db.db.cursor()
_, sql, params = function_get_sql_clause(opts, **kwargs) _, sql, params = function_get_sql_clause(opts, **kwargs)
select = ['%s.%s' % (opts.db_table, f) for f in fields] select = ['%s.%s' % (db.db.quote_name(opts.db_table), db.db.quote_name(f)) for f in fields]
cursor.execute("SELECT " + (kwargs.get('distinct') and "DISTINCT " or "") + ",".join(select) + sql, params) cursor.execute("SELECT " + (kwargs.get('distinct') and "DISTINCT " or "") + ",".join(select) + sql, params)
while 1: while 1:
rows = cursor.fetchmany(GET_ITERATOR_CHUNK_SIZE) rows = cursor.fetchmany(GET_ITERATOR_CHUNK_SIZE)
@ -1319,14 +1359,16 @@ def _fill_table_cache(opts, select, tables, where, old_prefix, cache_tables_seen
if f.rel and not f.null: if f.rel and not f.null:
db_table = f.rel.to.db_table db_table = f.rel.to.db_table
if db_table not in cache_tables_seen: if db_table not in cache_tables_seen:
tables.append(db_table) tables.append(db.db.quote_name(db_table))
else: # The table was already seen, so give it a table alias. else: # The table was already seen, so give it a table alias.
new_prefix = '%s%s' % (db_table, len(cache_tables_seen)) new_prefix = '%s%s' % (db_table, len(cache_tables_seen))
tables.append('%s %s' % (db_table, new_prefix)) tables.append('%s %s' % (db.db.quote_name(db_table), db.db.quote_name(new_prefix)))
db_table = new_prefix db_table = new_prefix
cache_tables_seen.append(db_table) cache_tables_seen.append(db_table)
where.append('%s.%s = %s.%s' % (old_prefix, f.column, db_table, f.rel.get_related_field().column)) where.append('%s.%s = %s.%s' % \
select.extend(['%s.%s' % (db_table, f2.column) for f2 in f.rel.to.fields]) (db.db.quote_name(old_prefix), db.db.quote_name(f.column),
db.db.quote_name(db_table), db.db.quote_name(f.rel.get_related_field().column)))
select.extend(['%s.%s' % (db.db.quote_name(db_table), db.db.quote_name(f2.column)) for f2 in f.rel.to.fields])
_fill_table_cache(f.rel.to, select, tables, where, db_table, cache_tables_seen) _fill_table_cache(f.rel.to, select, tables, where, db_table, cache_tables_seen)
def _throw_bad_kwarg_error(kwarg): def _throw_bad_kwarg_error(kwarg):
@ -1385,11 +1427,15 @@ def _parse_lookup(kwarg_items, opts, table_count=0):
# Try many-to-many relationships first... # Try many-to-many relationships first...
for f in current_opts.many_to_many: for f in current_opts.many_to_many:
if f.name == current: if f.name == current:
rel_table_alias = 't%s' % table_count rel_table_alias = db.db.quote_name('t%s' % table_count)
table_count += 1 table_count += 1
tables.append('%s %s' % (f.get_m2m_db_table(current_opts), rel_table_alias)) tables.append('%s %s' % \
join_where.append('%s.%s = %s.%s_id' % (current_table_alias, current_opts.pk.column, (db.db.quote_name(f.get_m2m_db_table(current_opts)), rel_table_alias))
rel_table_alias, current_opts.object_name.lower())) join_where.append('%s.%s = %s.%s' % \
(db.db.quote_name(current_table_alias),
db.db.quote_name(current_opts.pk.column),
rel_table_alias,
db.db.quote_name(current_opts.object_name.lower() + '_id')))
# Optimization: In the case of primary-key lookups, we # Optimization: In the case of primary-key lookups, we
# don't have to do an extra join. # don't have to do an extra join.
if lookup_list and lookup_list[0] == f.rel.to.pk.name and lookup_type == 'exact': if lookup_list and lookup_list[0] == f.rel.to.pk.name and lookup_type == 'exact':
@ -1400,9 +1446,13 @@ def _parse_lookup(kwarg_items, opts, table_count=0):
param_required = False param_required = False
else: else:
new_table_alias = 't%s' % table_count new_table_alias = 't%s' % table_count
tables.append('%s %s' % (f.rel.to.db_table, new_table_alias)) tables.append('%s %s' % (db.db.quote_name(f.rel.to.db_table),
join_where.append('%s.%s_id = %s.%s' % (rel_table_alias, f.rel.to.object_name.lower(), db.db.quote_name(new_table_alias)))
new_table_alias, f.rel.to.pk.column)) join_where.append('%s.%s = %s.%s' % \
(db.db.quote_name(rel_table_alias),
db.db.quote_name(f.rel.to.object_name.lower() + '_id'),
db.db.quote_name(new_table_alias),
db.db.quote_name(f.rel.to.pk.column)))
current_table_alias = new_table_alias current_table_alias = new_table_alias
param_required = True param_required = True
current_opts = f.rel.to current_opts = f.rel.to
@ -1425,9 +1475,11 @@ def _parse_lookup(kwarg_items, opts, table_count=0):
params.extend(f.get_db_prep_lookup(lookup_type, kwarg_value)) params.extend(f.get_db_prep_lookup(lookup_type, kwarg_value))
else: else:
new_table_alias = 't%s' % table_count new_table_alias = 't%s' % table_count
tables.append('%s %s' % (f.rel.to.db_table, new_table_alias)) tables.append('%s %s' % \
join_where.append('%s.%s = %s.%s' % (current_table_alias, f.column, \ (db.db.quote_name(f.rel.to.db_table), db.db.quote_name(new_table_alias)))
new_table_alias, f.rel.to.pk.column)) join_where.append('%s.%s = %s.%s' % \
(db.db.quote_name(current_table_alias), db.db.quote_name(f.column),
db.db.quote_name(new_table_alias), db.db.quote_name(f.rel.to.pk.column)))
current_table_alias = new_table_alias current_table_alias = new_table_alias
param_required = True param_required = True
current_opts = f.rel.to current_opts = f.rel.to
@ -1446,8 +1498,9 @@ def _parse_lookup(kwarg_items, opts, table_count=0):
return tables, join_where, where, params, table_count return tables, join_where, where, params, table_count
def function_get_sql_clause(opts, **kwargs): def function_get_sql_clause(opts, **kwargs):
select = ["%s.%s" % (opts.db_table, f.column) for f in opts.fields] select = ["%s.%s" % (db.db.quote_name(opts.db_table), db.db.quote_name(f.column)) for f in opts.fields]
tables = [opts.db_table] + (kwargs.get('tables') and kwargs['tables'][:] or []) tables = [opts.db_table] + (kwargs.get('tables') and kwargs['tables'][:] or [])
tables = [db.db.quote_name(t) for t in tables]
where = kwargs.get('where') and kwargs['where'][:] or [] where = kwargs.get('where') and kwargs['where'][:] or []
params = kwargs.get('params') and kwargs['params'][:] or [] params = kwargs.get('params') and kwargs['params'][:] or []
@ -1466,7 +1519,7 @@ def function_get_sql_clause(opts, **kwargs):
# Add any additional SELECTs passed in via kwargs. # Add any additional SELECTs passed in via kwargs.
if kwargs.get('select'): if kwargs.get('select'):
select.extend(['(%s) AS %s' % (s[1], s[0]) for s in kwargs['select']]) select.extend(['(%s) AS %s' % (db.db.quote_name(s[1]), db.db.quote_name(s[0])) for s in kwargs['select']])
# ORDER BY clause # ORDER BY clause
order_by = [] order_by = []
@ -1480,13 +1533,17 @@ def function_get_sql_clause(opts, **kwargs):
else: else:
col_name = f col_name = f
order = "ASC" order = "ASC"
if "." in col_name:
table_prefix, col_name = col_name.split('.', 1)
table_prefix = db.db.quote_name(table_prefix) + '.'
else:
# Use the database table as a column prefix if it wasn't given, # Use the database table as a column prefix if it wasn't given,
# and if the requested column isn't a custom SELECT. # and if the requested column isn't a custom SELECT.
if "." not in col_name and col_name not in [k[0] for k in kwargs.get('select', [])]: if "." not in col_name and col_name not in [k[0] for k in kwargs.get('select', [])]:
table_prefix = opts.db_table + '.' table_prefix = db.db.quote_name(opts.db_table) + '.'
else: else:
table_prefix = '' table_prefix = ''
order_by.append('%s%s %s' % (table_prefix, orderfield2column(col_name, opts), order)) order_by.append('%s%s %s' % (table_prefix, db.db.quote_name(orderfield2column(col_name, opts)), order))
order_by = ", ".join(order_by) order_by = ", ".join(order_by)
# LIMIT and OFFSET clauses # LIMIT and OFFSET clauses
@ -1501,7 +1558,7 @@ def function_get_sql_clause(opts, **kwargs):
def function_get_in_bulk(opts, klass, *args, **kwargs): def function_get_in_bulk(opts, klass, *args, **kwargs):
id_list = args and args[0] or kwargs['id_list'] id_list = args and args[0] or kwargs['id_list']
assert id_list != [], "get_in_bulk() cannot be passed an empty list." assert id_list != [], "get_in_bulk() cannot be passed an empty list."
kwargs['where'] = ["%s.%s IN (%s)" % (opts.db_table, opts.pk.column, ",".join(['%s'] * len(id_list)))] kwargs['where'] = ["%s.%s IN (%s)" % (db.db.quote_name(opts.db_table), db.db.quote_name(opts.pk.column), ",".join(['%s'] * len(id_list)))]
kwargs['params'] = id_list kwargs['params'] = id_list
obj_list = function_get_list(opts, klass, **kwargs) obj_list = function_get_list(opts, klass, **kwargs)
return dict([(getattr(o, opts.pk.attname), o) for o in obj_list]) return dict([(getattr(o, opts.pk.attname), o) for o in obj_list])
@ -1522,9 +1579,10 @@ def function_get_date_list(opts, field, *args, **kwargs):
assert order in ('ASC', 'DESC'), "'order' must be either 'ASC' or 'DESC'" assert order in ('ASC', 'DESC'), "'order' must be either 'ASC' or 'DESC'"
kwargs['order_by'] = [] # Clear this because it'll mess things up otherwise. kwargs['order_by'] = [] # Clear this because it'll mess things up otherwise.
if field.null: if field.null:
kwargs.setdefault('where', []).append('%s.%s IS NOT NULL' % (opts.db_table, field.column)) kwargs.setdefault('where', []).append('%s.%s IS NOT NULL' % \
(db.db.quote_name(opts.db_table), db.db.quote_name(field.column)))
select, sql, params = function_get_sql_clause(opts, **kwargs) select, sql, params = function_get_sql_clause(opts, **kwargs)
sql = 'SELECT %s %s GROUP BY 1 ORDER BY 1' % (db.get_date_trunc_sql(kind, '%s.%s' % (opts.db_table, field.column)), sql) sql = 'SELECT %s %s GROUP BY 1 ORDER BY 1' % (db.get_date_trunc_sql(kind, '%s.%s' % (db.db.quote_name(opts.db_table), db.db.quote_name(field.column))), sql)
cursor = db.db.cursor() cursor = db.db.cursor()
cursor.execute(sql, params) cursor.execute(sql, params)
# We have to manually run typecast_timestamp(str()) on the results, because # We have to manually run typecast_timestamp(str()) on the results, because

View File

@ -91,12 +91,25 @@ class User(meta.Model):
if not hasattr(self, '_group_perm_cache'): if not hasattr(self, '_group_perm_cache'):
import sets import sets
cursor = db.cursor() cursor = db.cursor()
cursor.execute(""" # The SQL below works out to the following, after DB quoting:
SELECT p.package, p.codename # cursor.execute("""
FROM auth_permissions p, auth_groups_permissions gp, auth_users_groups ug # SELECT p.package, p.codename
WHERE p.id = gp.permission_id # FROM auth_permissions p, auth_groups_permissions gp, auth_users_groups ug
AND gp.group_id = ug.group_id # WHERE p.id = gp.permission_id
AND ug.user_id = %s""", [self.id]) # AND gp.group_id = ug.group_id
# AND ug.user_id = %s""", [self.id])
sql = """
SELECT p.%s, p.%s
FROM %s p, %s gp, %s ug
WHERE p.%s = gp.%s
AND gp.%s = ug.%s
AND ug.%s = %%s""" % (
db.quote_name('package'), db.quote_name('codename'),
db.quote_name('auth_permissions'), db.quote_name('auth_groups_permissions'),
db.quote_name('auth_users_groups'), db.quote_name('id'),
db.quote_name('permission_id'), db.quote_name('group_id'),
db.quote_name('group_id'), db.quote_name('user_id'))
cursor.execute(sql, [self.id])
self._group_perm_cache = sets.Set(["%s.%s" % (row[0], row[1]) for row in cursor.fetchall()]) self._group_perm_cache = sets.Set(["%s.%s" % (row[0], row[1]) for row in cursor.fetchall()])
return self._group_perm_cache return self._group_perm_cache

View File

@ -62,11 +62,11 @@ class BlockTranslateNode(Node):
context.push() context.push()
for var,val in self.extra_context.items(): for var,val in self.extra_context.items():
context[var] = resolve_variable_with_filters(val, context) context[var] = resolve_variable_with_filters(val, context)
singular = self.render_token_list(self.singular) % context singular = self.render_token_list(self.singular)
if self.plural and self.countervar and self.counter: if self.plural and self.countervar and self.counter:
count = resolve_variable_with_filters(self.counter, context) count = resolve_variable_with_filters(self.counter, context)
context[self.countervar] = count context[self.countervar] = count
plural = self.render_token_list(self.plural) % context plural = self.render_token_list(self.plural)
result = translation.ngettext(singular, plural, count) % context result = translation.ngettext(singular, plural, count) % context
else: else:
result = translation.gettext(singular) % context result = translation.gettext(singular) % context

View File

@ -27,6 +27,9 @@ from xml.parsers.expat import ExpatError
def rfc2822_date(date): def rfc2822_date(date):
return email.Utils.formatdate(time.mktime(date.timetuple())) return email.Utils.formatdate(time.mktime(date.timetuple()))
def rfc3339_date(date):
return date.strftime('%Y-%m-%dT%H:%M:%SZ')
def get_tag_uri(url, date): def get_tag_uri(url, date):
"Creates a TagURI. See http://diveintomark.org/archives/2004/05/28/howto-atom-id" "Creates a TagURI. See http://diveintomark.org/archives/2004/05/28/howto-atom-id"
tag = re.sub('^http://', '', url) tag = re.sub('^http://', '', url)
@ -38,7 +41,8 @@ def get_tag_uri(url, date):
class SyndicationFeed: class SyndicationFeed:
"Base class for all syndication feeds. Subclasses should provide write()" "Base class for all syndication feeds. Subclasses should provide write()"
def __init__(self, title, link, description, language=None, author_email=None, def __init__(self, title, link, description, language=None, author_email=None,
author_name=None, author_link=None, subtitle=None, categories=None): author_name=None, author_link=None, subtitle=None, categories=None,
feed_url=None):
self.feed = { self.feed = {
'title': title, 'title': title,
'link': link, 'link': link,
@ -49,11 +53,12 @@ class SyndicationFeed:
'author_link': author_link, 'author_link': author_link,
'subtitle': subtitle, 'subtitle': subtitle,
'categories': categories or (), 'categories': categories or (),
'feed_url': feed_url,
} }
self.items = [] self.items = []
def add_item(self, title, link, description, author_email=None, def add_item(self, title, link, description, author_email=None,
author_name=None, pubdate=None, comments=None, author_name=None, author_link=None, pubdate=None, comments=None,
unique_id=None, enclosure=None, categories=()): unique_id=None, enclosure=None, categories=()):
""" """
Adds an item to the feed. All args are expected to be Python Unicode Adds an item to the feed. All args are expected to be Python Unicode
@ -66,6 +71,7 @@ class SyndicationFeed:
'description': description, 'description': description,
'author_email': author_email, 'author_email': author_email,
'author_name': author_name, 'author_name': author_name,
'author_link': author_link,
'pubdate': pubdate, 'pubdate': pubdate,
'comments': comments, 'comments': comments,
'unique_id': unique_id, 'unique_id': unique_id,
@ -187,9 +193,11 @@ class Atom1Feed(SyndicationFeed):
else: else:
handler.startElement(u"feed", {u"xmlns": self.ns}) handler.startElement(u"feed", {u"xmlns": self.ns})
handler.addQuickElement(u"title", self.feed['title']) handler.addQuickElement(u"title", self.feed['title'])
handler.addQuickElement(u"link", "", {u"href": self.feed['link']}) handler.addQuickElement(u"link", "", {u"rel": u"alternate", u"href": self.feed['link']})
if self.feed['feed_url'] is not None:
handler.addQuickElement(u"link", "", {u"rel": u"self", u"href": self.feed['feed_url']})
handler.addQuickElement(u"id", self.feed['link']) handler.addQuickElement(u"id", self.feed['link'])
handler.addQuickElement(u"updated", rfc2822_date(self.latest_post_date()).decode('ascii')) handler.addQuickElement(u"updated", rfc3339_date(self.latest_post_date()).decode('ascii'))
if self.feed['author_name'] is not None: if self.feed['author_name'] is not None:
handler.startElement(u"author", {}) handler.startElement(u"author", {})
handler.addQuickElement(u"name", self.feed['author_name']) handler.addQuickElement(u"name", self.feed['author_name'])
@ -209,9 +217,9 @@ class Atom1Feed(SyndicationFeed):
for item in self.items: for item in self.items:
handler.startElement(u"entry", {}) handler.startElement(u"entry", {})
handler.addQuickElement(u"title", item['title']) handler.addQuickElement(u"title", item['title'])
handler.addQuickElement(u"link", item['link']) handler.addQuickElement(u"link", u"", {u"href": item['link']})
if item['pubdate'] is not None: if item['pubdate'] is not None:
handler.addQuickElement(u"updated", rfc2822_date(item['pubdate']).decode('ascii')) handler.addQuickElement(u"updated", rfc3339_date(item['pubdate']).decode('ascii'))
# Author information. # Author information.
if item['author_name'] is not None: if item['author_name'] is not None:
@ -219,6 +227,8 @@ class Atom1Feed(SyndicationFeed):
handler.addQuickElement(u"name", item['author_name']) handler.addQuickElement(u"name", item['author_name'])
if item['author_email'] is not None: if item['author_email'] is not None:
handler.addQuickElement(u"email", item['author_email']) handler.addQuickElement(u"email", item['author_email'])
if item['author_link'] is not None:
handler.addQuickElement(u"uri", item['author_link'])
handler.endElement(u"author") handler.endElement(u"author")
# Unique ID. # Unique ID.

439
django/views/debug.py Normal file
View File

@ -0,0 +1,439 @@
import os
import sys
import inspect
from django.conf import settings
from os.path import dirname, join as pathjoin
from django.core.template import Template, Context
from django.utils.httpwrappers import HttpResponseServerError, HttpResponseNotFound
def technical_500_response(request, exc_type, exc_value, tb):
"""
Create a technical server error response. The last three arguments are
the values returned from sys.exc_info() and friends.
"""
frames = []
while tb is not None:
filename = tb.tb_frame.f_code.co_filename
function = tb.tb_frame.f_code.co_name
lineno = tb.tb_lineno - 1
pre_context_lineno, pre_context, context_line, post_context = _get_lines_from_file(filename, lineno, 7)
frames.append({
'tb' : tb,
'filename' : filename,
'function' : function,
'lineno' : lineno,
'vars' : tb.tb_frame.f_locals,
'id' : id(tb),
'pre_context' : pre_context,
'context_line' : context_line,
'post_context' : post_context,
'pre_context_lineno' : pre_context_lineno,
})
tb = tb.tb_next
t = Template(TECHNICAL_500_TEMPLATE)
c = Context({
'exception_type' : exc_type.__name__,
'exception_value' : exc_value,
'frames' : frames,
'lastframe' : frames[-1],
'request' : request,
'request_protocol' : os.environ.get("HTTPS") == "on" and "https" or "http",
'settings' : dict([(k, getattr(settings, k)) for k in dir(settings) if k.isupper()]),
})
return HttpResponseServerError(t.render(c))
def technical_404_response(request, exception):
"""
Create a technical 404 error response. The exception should be the Http404
exception.
"""
try:
tried = exception.args[0]['tried']
except (IndexError, TypeError):
tried = []
t = Template(TECHNICAL_404_TEMPLATE)
c = Context({
'root_urlconf' : settings.ROOT_URLCONF,
'urlpatterns' : tried,
'reason' : str(exception),
'request' : request,
'request_protocol' : os.environ.get("HTTPS") == "on" and "https" or "http",
'settings' : dict([(k, getattr(settings, k)) for k in dir(settings) if k.isupper()]),
})
return HttpResponseNotFound(t.render(c))
def _get_lines_from_file(filename, lineno, context_lines):
"""
Returns context_lines before and after lineno from file.
Returns (pre_context_lineno, pre_context, context_line, post_context).
"""
try:
source = open(filename).readlines()
lower_bound = max(0, lineno - context_lines)
upper_bound = lineno + context_lines
pre_context = [line.strip('\n') for line in source[lower_bound:lineno]]
context_line = source[lineno].strip('\n')
post_context = [line.strip('\n') for line in source[lineno+1:upper_bound]]
return lower_bound, pre_context, context_line, post_context
except (OSError, IOError):
return None, [], None, []
#
# Templates are embedded in the file so that we know the error handler will
# always work even if the template loader is broken.
#
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" />
<title>{{ exception_type }} at {{ request.path }}</title>
<style type="text/css">
html * { padding:0; margin:0; }
body * { padding:10px 20px; }
body * * { padding:0; }
body { font:small sans-serif; }
body>div { border-bottom:1px solid #ddd; }
h1 { font-weight:normal; }
h2 { margin-bottom:.8em; }
h2 span { font-size:80%; color:#666; font-weight:normal; }
h3 { margin:1em 0 .5em 0; }
h4 { margin:0 0 .5em 0; font-weight: normal; }
table { border:1px solid #ccc; border-collapse: collapse; width:100%; background:white; }
tbody td, tbody th { vertical-align:top; padding:2px 3px; }
thead th { padding:1px 6px 1px 3px; background:#fefefe; text-align:left; font-weight:normal; font-size:11px; border:1px solid #ddd; }
tbody th { width:12em; text-align:right; color:#666; padding-right:.5em; }
table.vars { margin:5px 0 2px 40px; }
table.vars td, table.req td { font-family:monospace; }
table td.code { width:100%; }
table td.code div { overflow:hidden; }
ul.traceback { list-style-type:none; }
ul.traceback li.frame { margin-bottom:1em; }
div.context { margin: 10px 0; }
div.context ol { padding-left:30px; margin:0 10px; list-style-position: inside; }
div.context ol li { font-family:monospace; white-space:pre; color:#666; }
div.context ol.context-line li { color:black; background-color:#ccc; cursor:pointer; }
div.commands { margin-left: 40px; }
div.commands a { color:black; text-decoration:none; }
#summary { background: #ffc; }
#summary h2 { font-weight: normal; color: #666; }
#explanation { background:#eee; }
#traceback { background:#eee; }
#requestinfo { background:#f6f6f6; padding-left:120px; }
#summary table { border:none; background:transparent; }
#requestinfo h2, #requestinfo h3 { position:relative; margin-left:-100px; }
#requestinfo h3 { margin-bottom:-1em; }
</style>
<script type="text/javascript">
function getElementsByClassName(oElm, strTagName, strClassName){
// Written by Jonathan Snook, http://www.snook.ca/jon; Add-ons by Robert Nyman, http://www.robertnyman.com
var arrElements = (strTagName == "*" && document.all)? document.all :
oElm.getElementsByTagName(strTagName);
var arrReturnElements = new Array();
strClassName = strClassName.replace(/\-/g, "\\-");
var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$)");
var oElement;
for(var i=0; i<arrElements.length; i++){
oElement = arrElements[i];
if(oRegExp.test(oElement.className)){
arrReturnElements.push(oElement);
}
}
return (arrReturnElements)
}
function hideAll(elems) {
for (var e = 0; e < elems.length; e++) {
elems[e].style.display = 'none';
}
}
window.onload = function() {
hideAll(getElementsByClassName(document, 'table', 'vars'));
hideAll(getElementsByClassName(document, 'ol', 'pre-context'));
hideAll(getElementsByClassName(document, 'ol', 'post-context'));
}
function toggle() {
for (var i = 0; i < arguments.length; i++) {
var e = document.getElementById(arguments[i]);
if (e) {
e.style.display = e.style.display == 'none' ? 'block' : 'none';
}
}
return false;
}
function varToggle(link, id) {
toggle('v' + id);
var s = link.getElementsByTagName('span')[0];
var uarr = String.fromCharCode(0x2191);
var darr = String.fromCharCode(0x2193);
s.innerHTML = s.innerHTML == uarr ? darr : uarr;
return false;
}
</script>
</head>
<body>
<div id="summary">
<h1>{{ exception_type }} at {{ request.path }}</h1>
<h2>{{ exception_value }}</h2>
<table class="meta">
<tr>
<th>Request Method:</th>
<td>{{ request.META.REQUEST_METHOD }}</td>
</tr>
<tr>
<th>Request URL:</th>
<td>{{ request_protocol }}://{{ request.META.HTTP_HOST }}{{ request.path }}</td>
</tr>
<tr>
<th>Exception Type:</th>
<td>{{ exception_type }}</td>
</tr>
<tr>
<th>Exception Value:</th>
<td>{{ exception_value }}</td>
</tr>
<tr>
<th>Exception Location:</th>
<td>{{ lastframe.filename }} in {{ lastframe.function }}, line {{ lastframe.lineno }}</td>
</tr>
</table>
</div>
<div id="traceback">
<h2>Traceback <span>(innermost last)</span></h2>
<ul class="traceback">
{% for frame in frames %}
<li class="frame">
<code>{{ frame.filename }}</code> in <code>{{ frame.function }}</code>
{% if frame.context_line %}
<div class="context" id="c{{ frame.id }}">
{% if frame.pre_context %}
<ol start="{{ frame.pre_context_lineno }}" class="pre-context" id="pre{{ frame.id }}">{% for line in frame.pre_context %}<li>{{ line|escape }}</li>{% endfor %}</ol>
{% endif %}
<ol start="{{ frame.lineno }}" class="context-line"><li onclick="toggle('pre{{ frame.id }}', 'post{{ frame.id }}')">{{ frame.context_line|escape }}</li></ol>
{% if frame.post_context %}
<ol start='{{ frame.lineno|add:"1" }}' class="post-context" id="post{{ frame.id }}">{% for line in frame.post_context %}<li>{{ line|escape }}</li>{% endfor %}</ol>
{% endif %}
</div>
{% endif %}
{% if frame.vars %}
<div class="commands">
<a href="#" onclick="return varToggle(this, '{{ frame.id }}')">Local vars <span>&darr;</span> </a>
</div>
<table class="vars" id="v{{ frame.id }}">
<thead>
<tr>
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
{% for var in frame.vars.items|dictsort:"0" %}
<tr>
<td>{{ var.0 }}</td>
<td class="code"><div>{{ var.1|pprint|escape }}</div></td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
</li>
{% endfor %}
</ul>
</div>
<div id="requestinfo">
<h2>Request information</h2>
<h3 id="get-info">GET</h3>
{% if request.GET %}
<table class="req">
<thead>
<tr>
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
</tbody>
{% for var in request.GET.items %}
<tr>
<td>{{ var.0 }}</td>
<td class="code"><div>{{ var.1|pprint|escape }}</div></td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p>No GET data<p>
{% endif %}
<h3 id="post-info">POST</h3>
{% if request.POST %}
<table class="req">
<thead>
<tr>
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
</tbody>
{% for var in request.POST.items %}
<tr>
<td>{{ var.0 }}</td>
<td class="code"><div>{{ var.1|pprint|escape }}</div></td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p>No POST data<p>
{% endif %}
<h3 id="cookie-info">COOKIES</h3>
{% if request.COOKIES %}
<table class="req">
<thead>
<tr>
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
</tbody>
{% for var in request.COOKIES.items %}
<tr>
<td>{{ var.0 }}</td>
<td class="code"><div>{{ var.1|pprint|escape }}</div></td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p>No cookie data<p>
{% endif %}
<h3 id="meta-info">META</h3>
<table class="req">
<thead>
<tr>
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
</tbody>
{% for var in request.META.items|dictsort:"0" %}
<tr>
<td>{{ var.0 }}</td>
<td class="code"><div>{{ var.1|pprint|escape }}</div></td>
</tr>
{% endfor %}
</tbody>
</table>
<h3 id="settings-info">Settings</h3>
<h4>Using settings module <code>{{ settings.SETTINGS_MODULE }}</code></h4>
<table class="req">
<thead>
<tr>
<th>Setting</th>
<th>Value</th>
</tr>
</thead>
</tbody>
{% for var in settings.items|dictsort:"0" %}
<tr>
<td>{{ var.0 }}</td>
<td class="code"><div>{{ var.1|pprint|escape }}</div></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div id="explanation">
<p>
You're seeing this error because you have <code>DEBUG = True</code> in your
Django settings file. Change that to <code>False</code>, and Django will
display a standard 500 page.
</p>
</div>
</body>
</html>
"""
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" />
<title>Page not found at {{ request.path }}</title>
<meta name="robots" content="NONE,NOARCHIVE" />
<style type="text/css">
html * { padding:0; margin:0; }
body * { padding:10px 20px; }
body * * { padding:0; }
body { font:small sans-serif; background:#eee; }
body>div { border-bottom:1px solid #ddd; }
h1 { font-weight:normal; margin-bottom:.4em; }
h1 span { font-size:60%; color:#666; font-weight:normal; }
table { border:none; border-collapse: collapse; width:100%; }
td, th { vertical-align:top; padding:2px 3px; }
th { width:12em; text-align:right; color:#666; padding-right:.5em; }
#info { background:#f6f6f6; }
#info ol { margin: 0.5em 4em; }
#info ol li { font-family: monospace; }
#summary { background: #ffc; }
#explanation { background:#eee; border-bottom: 0px none; }
</style>
</head>
<body>
<div id="summary">
<h1>Page not found <span>(404)</span></h1>
<table class="meta">
<tr>
<th>Request Method:</th>
<td>{{ request.META.REQUEST_METHOD }}</td>
</tr>
<tr>
<th>Request URL:</th>
<td>{{ request_protocol }}://{{ request.META.HTTP_HOST }}{{ request.path }}</td>
</tr>
</table>
</div>
<div id="info">
{% if urlpatterns %}
<p>
Using the URLconf defined in <code>{{ settings.ROOT_URLCONF }}</code>,
Django tried these URL patterns, in this order:
</p>
<ol>
{% for pattern in urlpatterns %}
<li>{{ pattern|escape }}</li>
{% endfor %}
</ol>
<p>The current URL, <code>{{ request.path }}</code>, didn't match any of these.</p>
{% else %}
<p>{{ reason|escape }}</p>
{% endif %}
</div>
<div id="explanation">
<p>
You're seeing this error because you have <code>DEBUG = True</code> in
your Django settings file. Change that to <code>False</code>, and Django
will display a standard 404 page.
</p>
</div>
</body>
</html>
"""

View File

@ -34,15 +34,21 @@ Django will use ``first_name`` and ``last_name`` as the database column names.
Each field type, except for ``ForeignKey``, ``ManyToManyField`` and Each field type, except for ``ForeignKey``, ``ManyToManyField`` and
``OneToOneField``, takes an optional first positional argument -- a ``OneToOneField``, takes an optional first positional argument -- a
human-readable name. If the human-readable name isn't given, Django will use human-readable name. If the human-readable name isn't given, Django will
the machine-readable name, converting underscores to spaces. automatically create the human-readable name by using the machine-readable
name, converting underscores to spaces.
Example:: In this example, the human-readable name is ``"Person's first name"``::
first_name = meta.CharField("Person's first name", maxlength=30) first_name = meta.CharField("Person's first name", maxlength=30)
For ``ForeignKey``, ``ManyToManyField`` and ``OneToOneField``, use the In this example, the human-readable name is ``"first name"``::
``verbose_name`` keyword argument::
first_name = meta.CharField(maxlength=30)
``ForeignKey``, ``ManyToManyField`` and ``OneToOneField`` require the first
argument to be a model class, so use the ``verbose_name`` keyword argument to
specify the human-readable name::
poll = meta.ForeignKey(Poll, verbose_name="the related poll") poll = meta.ForeignKey(Poll, verbose_name="the related poll")
sites = meta.ManyToManyField(Site, verbose_name="list of sites") sites = meta.ManyToManyField(Site, verbose_name="list of sites")
@ -111,6 +117,11 @@ The following arguments are available to all field types. All are optional.
The name of the database column to use for this field. If this isn't given, The name of the database column to use for this field. If this isn't given,
Django will use the field's name. Django will use the field's name.
If your database column name is an SQL reserved word, or contains
characters that aren't allowed in Python variable names -- notably, the
hyphen -- that's OK. Django quotes column and table names behind the
scenes.
``db_index`` ``db_index``
If ``True``, ``django-admin.py sqlindexes`` will output a ``CREATE INDEX`` If ``True``, ``django-admin.py sqlindexes`` will output a ``CREATE INDEX``
statement for this field. statement for this field.
@ -700,6 +711,10 @@ Here's a list of all possible ``META`` options. No options are required. Adding
If this isn't given, Django will use ``app_label + '_' + module_name``. If this isn't given, Django will use ``app_label + '_' + module_name``.
If your database table name is an SQL reserved word, or contains characters
that aren't allowed in Python variable names -- notably, the hyphen --
that's OK. Django quotes column and table names behind the scenes.
``exceptions`` ``exceptions``
Names of extra exception subclasses to include in the generated module. Names of extra exception subclasses to include in the generated module.
These exceptions are available from instance methods and from module-level These exceptions are available from instance methods and from module-level
@ -732,8 +747,8 @@ Here's a list of all possible ``META`` options. No options are required. Adding
module_name = "pizza_orders" module_name = "pizza_orders"
If this isn't given, Django will use a lowercased version of the class If this isn't given, Django will use a lowercased version of the class
name, plus "s". This "poor man's pluralization" is intentional: Any other name, plus ``"s"``. This "poor man's pluralization" is intentional: Any
level of magic pluralization would get confusing. other level of magic pluralization would get confusing.
``order_with_respect_to`` ``order_with_respect_to``
Marks this object as "orderable" with respect to the given field. This is Marks this object as "orderable" with respect to the given field. This is

View File

@ -266,6 +266,21 @@ comes directly from your `LANGUAGE_CODE setting`_.
.. _LANGUAGE_CODE setting: http://www.djangoproject.com/documentation/settings/#language-code .. _LANGUAGE_CODE setting: http://www.djangoproject.com/documentation/settings/#language-code
URLs
----
The ``link`` method/attribute can return either an absolute URL (e.g.
``"/blog/"``) or a URL with the fully-qualified domain and protocol (e.g.
``"http://www.example.com/blog/"``). If ``link`` doesn't return the domain,
the syndication framework will insert the domain of the current site, according
to your `SITE_ID setting`_.
Atom feeds require a ``<link rel="self">`` that defines the feed's current
location. The syndication framework populates this automatically, using the
domain of the current site according to the SITE_ID setting.
.. _SITE_ID setting: http://www.djangoproject.com/documentation/settings/#site-id
Publishing Atom and RSS feeds in tandem Publishing Atom and RSS feeds in tandem
--------------------------------------- ---------------------------------------
@ -371,6 +386,55 @@ This example illustrates all possible attributes and methods for a ``Feed`` clas
description = 'Foo bar baz.' # Hard-coded description. description = 'Foo bar baz.' # Hard-coded description.
# AUTHOR NAME --One of the following three is optional. The framework
# looks for them in this order.
def author_name(self, obj):
"""
Takes the object returned by get_object() and returns the feed's
author's name as a normal Python string.
"""
def author_name(self):
"""
Returns the feed's author's name as a normal Python string.
"""
author_name = 'Sally Smith' # Hard-coded author name.
# AUTHOR E-MAIL --One of the following three is optional. The framework
# looks for them in this order.
def author_email(self, obj):
"""
Takes the object returned by get_object() and returns the feed's
author's e-mail as a normal Python string.
"""
def author_name(self):
"""
Returns the feed's author's e-mail as a normal Python string.
"""
author_email = 'test@example.com' # Hard-coded author e-mail.
# AUTHOR LINK --One of the following three is optional. The framework
# looks for them in this order. In each case, the URL should include
# the "http://" and domain name.
def author_link(self, obj):
"""
Takes the object returned by get_object() and returns the feed's
author's URL as a normal Python string.
"""
def author_link(self):
"""
Returns the feed's author's URL as a normal Python string.
"""
author_link = 'http://www.example.com/' # Hard-coded author URL.
# ITEMS -- One of the following three is required. The framework looks # ITEMS -- One of the following three is required. The framework looks
# for them in this order. # for them in this order.
@ -413,6 +477,59 @@ This example illustrates all possible attributes and methods for a ``Feed`` clas
Returns the URL for every item in the feed. Returns the URL for every item in the feed.
""" """
# ITEM AUTHOR NAME --One of the following three is optional. The
# framework looks for them in this order.
def item_author_name(self, item):
"""
Takes an item, as returned by items(), and returns the item's
author's name as a normal Python string.
"""
def item_author_name(self):
"""
Returns the author name for every item in the feed.
"""
item_author_name = 'Sally Smith' # Hard-coded author name.
# ITEM AUTHOR E-MAIL --One of the following three is optional. The
# framework looks for them in this order.
#
# If you specify this, you must specify item_author_name.
def item_author_email(self, obj):
"""
Takes an item, as returned by items(), and returns the item's
author's e-mail as a normal Python string.
"""
def item_author_email(self):
"""
Returns the author e-mail for every item in the feed.
"""
item_author_email = 'test@example.com' # Hard-coded author e-mail.
# ITEM AUTHOR LINK --One of the following three is optional. The
# framework looks for them in this order. In each case, the URL should
# include the "http://" and domain name.
#
# If you specify this, you must specify item_author_name.
def item_author_link(self, obj):
"""
Takes an item, as returned by items(), and returns the item's
author's URL as a normal Python string.
"""
def item_author_link(self):
"""
Returns the author URL for every item in the feed.
"""
item_author_link = 'http://www.example.com/' # Hard-coded author URL.
# ITEM ENCLOSURE URL -- One of these three is required if you're # ITEM ENCLOSURE URL -- One of these three is required if you're
# publishing enclosures. The framework looks for them in this order. # publishing enclosures. The framework looks for them in this order.
@ -501,7 +618,8 @@ Each of these three classes knows how to render a certain type of feed as XML.
They share this interface: They share this interface:
``__init__(title, link, description, language=None, author_email=None,`` ``__init__(title, link, description, language=None, author_email=None,``
``author_name=None, author_link=None, subtitle=None, categories=None)`` ``author_name=None, author_link=None, subtitle=None, categories=None,``
``feed_url=None)``
Initializes the feed with the given metadata, which applies to the entire feed Initializes the feed with the given metadata, which applies to the entire feed
(i.e., not just to a specific item in the feed). (i.e., not just to a specific item in the feed).

View File

@ -1,4 +1,4 @@
__all__ = ['basic', 'repr', 'custom_methods', 'many_to_one', 'many_to_many', __all__ = ['basic', 'repr', 'custom_methods', 'many_to_one', 'many_to_many',
'ordering', 'lookup', 'get_latest', 'm2m_intermediary', 'one_to_one', 'ordering', 'lookup', 'get_latest', 'm2m_intermediary', 'one_to_one',
'm2o_recursive', 'm2o_recursive2', 'save_delete_hooks', 'custom_pk', 'm2o_recursive', 'm2o_recursive2', 'save_delete_hooks', 'custom_pk',
'subclassing', 'many_to_one_null', 'custom_columns'] 'subclassing', 'many_to_one_null', 'custom_columns', 'reserved_names']

View File

@ -0,0 +1,47 @@
"""
18. Using SQL reserved names
Need to use a reserved SQL name as a column name or table name? Need to include
a hyphen in a column or table name? No problem. Django quotes names
appropriately behind the scenes, so your database won't complain about
reserved-name usage.
"""
from django.core import meta
class Thing(meta.Model):
when = meta.CharField(maxlength=1, primary_key=True)
join = meta.CharField(maxlength=1)
like = meta.CharField(maxlength=1)
drop = meta.CharField(maxlength=1)
alter = meta.CharField(maxlength=1)
having = meta.CharField(maxlength=1)
where = meta.CharField(maxlength=1)
has_hyphen = meta.CharField(maxlength=1, db_column='has-hyphen')
class META:
db_table = 'select'
def __repr__(self):
return self.when
API_TESTS = """
>>> t = things.Thing(when='a', join='b', like='c', drop='d', alter='e', having='f', where='g', has_hyphen='h')
>>> t.save()
>>> print t.when
a
>>> u = things.Thing(when='h', join='i', like='j', drop='k', alter='l', having='m', where='n')
>>> u.save()
>>> print u.when
h
>>> things.get_list(order_by=['when'])
[a, h]
>>> v = things.get_object(pk='a')
>>> print v.join
b
>>> print v.where
g
>>> things.get_list(order_by=['select.when'])
[a, h]
"""