1
0
mirror of https://github.com/django/django.git synced 2025-07-05 02:09:13 +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():
# Clean up old database records
cursor = db.cursor()
cursor.execute("DELETE FROM core_sessions WHERE expire_date < NOW()")
cursor.execute("DELETE FROM registration_challenges WHERE request_date < NOW() - INTERVAL '1 week'")
cursor.execute("DELETE FROM %s WHERE %s < NOW()" % \
(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()
if __name__ == "__main__":

View File

@ -14,8 +14,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\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"
"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"
"X-Poedit-Language: Czech\n"
"X-Poedit-Country: CZECH REPUBLIC\n"
@ -263,12 +262,8 @@ msgid "Server Error <em>(500)</em>"
msgstr "Chyba serveru <em>(500)</em>"
#: contrib/admin/templates/admin/500.html:10
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."
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."
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."
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:8
@ -359,13 +354,8 @@ msgstr "Odhlásit se"
#: contrib/admin/templates/admin/delete_confirmation.html:7
#, fuzzy, python-format
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:"
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ů:"
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:"
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
msgid "View on site"
@ -408,12 +398,8 @@ msgstr "aktivní"
#: contrib/admin/templates/admin/delete_confirmation.html:14
#, python-format
msgid ""
"Are you sure you want to delete the %(object_name)s \"%(object)s\"? All of "
"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:"
msgid "Are you sure you want to delete the %(object_name)s \"%(object)s\"? All of 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
msgid "Yes, I'm sure"
@ -442,12 +428,8 @@ msgid "Password reset"
msgstr "Obnovení hesla"
#: contrib/admin/templates/registration/password_reset_form.html:12
msgid ""
"Forgotten your password? Enter your e-mail address below, and we'll reset "
"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é."
msgid "Forgotten your password? Enter your e-mail address below, and we'll reset 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
msgid "E-mail address:"
@ -471,20 +453,12 @@ msgid "Password reset successful"
msgstr "Obnovení hesla bylo úspěšné"
#: contrib/admin/templates/registration/password_reset_done.html:12
msgid ""
"We've e-mailed a new password to the e-mail address you submitted. You "
"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."
msgid "We've e-mailed a new password to the e-mail address you submitted. You 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
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."
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ě."
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."
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
msgid "Old password:"
@ -567,15 +541,15 @@ msgstr ""
#: utils/translation.py:335
msgid "DATE_FORMAT"
msgstr ""
msgstr "Formát data"
#: utils/translation.py:336
msgid "DATETIME_FORMAT"
msgstr ""
msgstr "Formát data a času"
#: utils/translation.py:337
msgid "TIME_FORMAT"
msgstr ""
msgstr "Formát času"
#: utils/dates.py:6
msgid "Monday"
@ -613,23 +587,28 @@ msgstr "Leden"
msgid "February"
msgstr "Únor"
#: utils/dates.py:14 utils/dates.py:27
#: utils/dates.py:14
#: utils/dates.py:27
msgid "March"
msgstr "Březen"
#: utils/dates.py:14 utils/dates.py:27
#: utils/dates.py:14
#: utils/dates.py:27
msgid "April"
msgstr "Duben"
#: utils/dates.py:14 utils/dates.py:27
#: utils/dates.py:14
#: utils/dates.py:27
msgid "May"
msgstr "Květen"
#: utils/dates.py:14 utils/dates.py:27
#: utils/dates.py:14
#: utils/dates.py:27
msgid "June"
msgstr "Červen"
#: utils/dates.py:15 utils/dates.py:27
#: utils/dates.py:15
#: utils/dates.py:27
msgid "July"
msgstr "Červenec"
@ -701,7 +680,10 @@ msgstr "weby"
msgid "label"
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"
msgstr "jméno"
@ -832,7 +814,8 @@ msgstr "codename"
msgid "Permission"
msgstr "Oprávnění"
#: models/auth.py:11 models/auth.py:58
#: models/auth.py:11
#: models/auth.py:58
msgid "Permissions"
msgstr "Oprávnění"
@ -840,7 +823,8 @@ msgstr "Oprávnění"
msgid "Group"
msgstr "Skupina"
#: models/auth.py:23 models/auth.py:60
#: models/auth.py:23
#: models/auth.py:60
msgid "Groups"
msgstr "Skupiny"
@ -894,12 +878,8 @@ msgid "date joined"
msgstr "datum zaregistrování"
#: models/auth.py:44
msgid ""
"In addition to the permissions manually assigned, this user will also get "
"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."
msgid "In addition to the permissions manually assigned, this user will also get 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
msgid "Users"
@ -951,7 +931,7 @@ msgstr "Galicijsky"
#: conf/global_settings.py:44
msgid "Icelandic"
msgstr ""
msgstr "Islandština"
#: conf/global_settings.py:45
msgid "Italian"
@ -987,8 +967,7 @@ msgstr "Tato hodnota musí obsahovat pouze znaky, čísla nebo podtržítka."
#: core/validators.py:63
msgid "This value must contain only letters, numbers, underscores and slashes."
msgstr ""
"Tato hodnota musí obsahovat pouze znaky, čísla, podtržítka nebo lomítka."
msgstr "Tato hodnota musí obsahovat pouze znaky, čísla, podtržítka nebo lomítka."
#: core/validators.py:71
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."
#: core/validators.py:147
msgid ""
"Upload a valid image. The file you uploaded was either not an image or a "
"corrupted image."
msgstr ""
"Nahrajte na server platný obrázek. Soubor, který jste nahrál(a) nebyl "
"obrázek, nebo byl porušen."
msgid "Upload a valid image. The file you uploaded was either not an image or a 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
#, python-format
@ -1092,7 +1067,8 @@ msgstr "Špatně formované XML: %s"
msgid "Invalid URL: %s"
msgstr "Neplatné URL: %s"
#: core/validators.py:205 core/validators.py:207
#: core/validators.py:205
#: core/validators.py:207
#, python-format
msgid "The URL %s is a broken link."
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."
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."
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
#, python-format
msgid "Please enter a valid decimal number with at most %s total digit."
msgid_plural ""
"Please enter a valid decimal number with at most %s total digits."
msgid_plural "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[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."
@ -1157,16 +1133,10 @@ msgstr[2] "Prosíme, vložte platné číslo s nejvíce %s ciframi celkem."
#: core/validators.py:351
#, python-format
msgid "Please enter a valid decimal number with at most %s decimal place."
msgid_plural ""
"Please enter a valid decimal number with at most %s decimal places."
msgstr[0] ""
"Prosíme, vložte platné číslo s nejvíce %s cifrou 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."
msgid_plural "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[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
#, python-format
@ -1193,71 +1163,44 @@ msgstr "Nemohl jsem získat nic z %s."
#: core/validators.py:428
#, python-format
msgid ""
"The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
msgid "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'."
#: core/validators.py:461
#, python-format
msgid ""
"Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with "
"\"%(start)s\".)"
msgstr ""
"Prosíme, zavřete nezavřenou značku %(tag)s z řádky %(line)s. (Řádka začíná s "
"\"%(start)s\".)"
msgid "Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with \"%(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
#, python-format
msgid ""
"Some text starting on line %(line)s is not allowed in that context. (Line "
"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\".)"
msgid "Some text starting on line %(line)s is not allowed in that context. (Line 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
#, python-format
msgid ""
"\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%"
"(start)s\".)"
msgstr ""
"\"%(attr)s\" na řádce %(line)s je neplatný atribut. (Řádka začíná s \"%"
"(start)s\".)"
msgid "\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%(start)s\".)"
msgstr "\"%(attr)s\" na řádce %(line)s je neplatný atribut. (Řádka začíná s \"%(start)s\".)"
#: core/validators.py:475
#, python-format
msgid ""
"\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%"
"(start)s\".)"
msgstr ""
"\"<%(tag)s>\" na řádce %(line)s je neplatná značka. (Řádka začíná s \"%"
"(start)s\".)"
msgid "\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%(start)s\".)"
msgstr "\"<%(tag)s>\" na řádce %(line)s je neplatná značka. (Řádka začíná s \"%(start)s\".)"
#: core/validators.py:479
#, python-format
msgid ""
"A tag on line %(line)s is missing one or more required attributes. (Line "
"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\".)"
msgid "A tag on line %(line)s is missing one or more required attributes. (Line 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
#, python-format
msgid ""
"The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line "
"starts with \"%(start)s\".)"
msgstr ""
"Atribut \"%(attr)s\" na řádce %(line)s má neplatnou hodnotu. (Řádka začína s "
"\"%(start)s\".)"
msgid "The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line 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
msgid " Separate multiple IDs with commas."
msgstr "Oddělte více identifikátorů čárkami."
#: core/meta/fields.py:117
msgid ""
" 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."
msgid " 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."

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"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\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"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
@ -568,18 +568,6 @@ msgstr "záznamy priebehu"
msgid "All dates"
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
msgid "Monday"
msgstr "Pondelok"
@ -684,6 +672,18 @@ msgstr ""
msgid "Dec."
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
msgid "domain name"
msgstr "meno domény"
@ -916,7 +916,7 @@ msgstr "Osobné údaje"
msgid "Important dates"
msgstr "Dôležité údaje"
#: models/auth.py:182
#: models/auth.py:195
msgid "Message"
msgstr "Zpráva"

View File

@ -209,9 +209,9 @@ def items_for_result(cl, result):
result_repr = '&nbsp;'
if first: # First column is a special case
first = False
result_id = getattr(result, pk)
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))
url = cl.url_for_result(result)
yield ('<th%s><a href="%s"%s>%s</a></th>' % \
(row_class, url, (cl.is_popup and ' onclick="opener.dismissRelatedLookupPopup(window, %r); return false;"' % result_id or ''), result_repr))
else:
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
or _('Select %s to change') % self.opts.verbose_name)
self.get_filters(request)
self.pk_attname = self.lookup_opts.pk.attname
def get_filters(self, request):
self.filter_specs = []
@ -301,6 +302,9 @@ class ChangeList(object):
self.can_show_all, self.multi_page, self.paginator) = (result_count,
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):
lookup_opts, params = self.lookup_opts, self.params
# For ordering, first check the "ordering" parameter in the admin options,

View File

@ -17,8 +17,9 @@ class Feed:
item_enclosure_url = None
feed_type = feedgenerator.DefaultFeed
def __init__(self, slug):
def __init__(self, slug, feed_url):
self.slug = slug
self.feed_url = feed_url
def item_link(self, item):
try:
@ -26,8 +27,11 @@ class Feed:
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__
def __get_dynamic_attr(self, attname, obj):
attr = getattr(self, attname)
def __get_dynamic_attr(self, attname, obj, default=None):
try:
attr = getattr(self, attname)
except AttributeError:
return default
if callable(attr):
try:
return attr(obj)
@ -56,7 +60,11 @@ class Feed:
title = self.__get_dynamic_attr('title', obj),
link = link,
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:
@ -78,6 +86,12 @@ class Feed:
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'),
)
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(
title = title_template.render(Context({'obj': item, 'site': current_site})).decode('utf-8'),
link = link,
@ -85,5 +99,8 @@ class Feed:
unique_id = link,
enclosure = enc,
pubdate = self.__get_dynamic_attr('item_pubdate', item),
author_name = author_name,
author_email = author_email,
author_link = author_link,
)
return feed

View File

@ -17,7 +17,7 @@ def feed(request, url, feed_dict=None):
raise Http404, "Slug %r isn't registered." % slug
try:
feedgen = f(slug).get_feed(param)
feedgen = f(slug, request.path).get_feed(param)
except feeds.FeedDoesNotExist:
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',
'OneToOneField': 'int',
'PhoneNumberField': 'varchar(20)',
'PositiveIntegerField': 'int CONSTRAINT [CK_int_pos_%(name)s] CHECK ([%(name)s] > 0)',
'PositiveSmallIntegerField': 'smallint CONSTRAINT [CK_smallint_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_%(column)s] CHECK ([%(column)s] > 0)',
'SlugField': 'varchar(50)',
'SmallIntegerField': 'smallint',
'TextField': 'text',

View File

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

View File

@ -86,14 +86,14 @@ class BaseHandler:
return response
except exceptions.Http404, e:
if DEBUG:
return self.get_technical_error_response(is404=True, exception=e)
return self.get_technical_error_response(request, is404=True, exception=e)
else:
callback, param_dict = resolver.resolve404()
return callback(request, **param_dict)
except db.DatabaseError:
db.db.rollback()
if DEBUG:
return self.get_technical_error_response()
return self.get_technical_error_response(request)
else:
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)
@ -103,7 +103,7 @@ class BaseHandler:
return httpwrappers.HttpResponseForbidden('<h1>Permission denied</h1>')
except: # Handle everything else, including SuspiciousOperation, etc.
if DEBUG:
return self.get_technical_error_response()
return self.get_technical_error_response(request)
else:
subject = 'Coding error (%s IP): %s' % ((request.META.get('REMOTE_ADDR') in INTERNAL_IPS and 'internal' or 'EXTERNAL'), getattr(request, 'path', ''))
try:
@ -123,35 +123,17 @@ class BaseHandler:
callback, param_dict = resolver.resolve500()
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
fundamental database or coding error.
"""
import sys
from django.views import debug
if is404:
from django.conf.settings import ROOT_URLCONF
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:
html.append('<p>Using the URLconf defined in <code>%s</code>, Django tried these URL patterns, in this order:</p>' % ROOT_URLCONF)
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))
return debug.technical_404_response(request, exception)
else:
output = "There's been an error:\n\n%s" % self._get_traceback()
return httpwrappers.HttpResponseServerError(output, mimetype='text/plain')
return debug.technical_500_response(request, *sys.exc_info())
def _get_traceback(self):
"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')
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):
return '%s_%s' % (action, opts.object_name.lower())
@ -33,12 +36,16 @@ def _get_all_permissions(opts):
return perms + list(opts.permissions)
def _get_permission_insert(name, codename, opts):
return "INSERT INTO auth_permissions (name, package, codename) VALUES ('%s', '%s', '%s');" % \
(name.replace("'", "''"), opts.app_label, codename)
from django.core.db import db
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):
return "INSERT INTO content_types (name, package, python_module_name) VALUES ('%s', '%s', '%s');" % \
(opts.verbose_name, opts.app_label, opts.module_name)
from django.core.db import db
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):
return bool(re.search(r'^\w+$', s))
@ -64,7 +71,7 @@ def get_sql_create(mod):
data_type = f.get_internal_type()
col_type = db.DATA_TYPES[data_type]
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 ''))
if f.unique:
field_output.append('UNIQUE')
@ -72,14 +79,16 @@ def get_sql_create(mod):
field_output.append('PRIMARY KEY')
if f.rel:
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))
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:
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.
full_statement.append(' %s%s' % (line, i < len(table_output)-1 and ',' or ''))
full_statement.append(');')
@ -88,13 +97,21 @@ def get_sql_create(mod):
for klass in mod._MODELS:
opts = klass._meta
for f in opts.many_to_many:
table_output = ['CREATE TABLE %s (' % f.get_m2m_db_table(opts)]
table_output.append(' id %s NOT NULL PRIMARY KEY,' % db.DATA_TYPES['AutoField'])
table_output.append(' %s_id %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))
table_output.append(' %s_id %s NOT NULL REFERENCES %s (%s),' % \
(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))
table_output.append(' UNIQUE (%s_id, %s_id)' % (opts.object_name.lower(), f.rel.to.object_name.lower()))
table_output = ['CREATE TABLE %s (' % db.db.quote_name(f.get_m2m_db_table(opts))]
table_output.append(' %s %s NOT NULL PRIMARY KEY,' % (db.db.quote_name('id'), db.DATA_TYPES['AutoField']))
table_output.append(' %s %s NOT NULL REFERENCES %s (%s),' % \
(db.db.quote_name(opts.object_name.lower() + '_id'),
db.DATA_TYPES[get_rel_data_type(opts.pk)] % opts.pk.__dict__,
db.db.quote_name(opts.db_table),
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(');')
final_output.append('\n'.join(table_output))
return final_output
@ -114,7 +131,7 @@ def get_sql_delete(mod):
try:
if cursor is not None:
# 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:
# The table doesn't exist, so it doesn't need to be dropped.
db.db.rollback()
@ -129,12 +146,12 @@ def get_sql_delete(mod):
try:
if cursor is not None:
# 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:
# The table doesn't exist, so it doesn't need to be dropped.
db.db.rollback()
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.
for klass in mod._MODELS:
@ -142,25 +159,31 @@ def get_sql_delete(mod):
for f in opts.many_to_many:
try:
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:
db.db.rollback()
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
# Delete from packages, auth_permissions, content_types.
output.append("DELETE FROM packages WHERE label = '%s';" % app_label)
output.append("DELETE FROM auth_permissions WHERE package = '%s';" % 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('packages'), db.db.quote_name('label'), 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.
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:
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
# 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):
"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 = []
for klass in mod._MODELS:
for f in klass._meta.fields:
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
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
def get_sql_indexes(mod):
"Returns a list of the CREATE INDEX SQL statements for the given module."
from django.core.db import db
output = []
for klass in mod._MODELS:
for f in klass._meta.fields:
if f.db_index:
unique = f.unique and "UNIQUE " or ""
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
get_sql_indexes.help_doc = "Prints the CREATE INDEX SQL statements for the given model module name(s)."
get_sql_indexes.args = APP_ARGS
@ -242,7 +269,8 @@ def database_check(mod):
app_label = mod._MODELS[0]._meta.app_label
# 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:
# sys.stderr.write("The '%s' package isn't installed.\n" % app_label)
print _get_packages_insert(app_label)
@ -256,34 +284,46 @@ def database_check(mod):
perms_seen.update(dict(perms))
contenttypes_seen[opts.module_name] = 1
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:
# sys.stderr.write("The '%s.%s' permission doesn't exist.\n" % (app_label, codename))
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:
# sys.stderr.write("The '%s.%s' content type doesn't exist.\n" % (app_label, opts.module_name))
print _get_contenttype_insert(opts)
# Check that there aren't any *extra* permissions in the DB that the model
# 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():
try:
perms_seen[row[0]]
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]))
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
# 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():
try:
contenttypes_seen[row[0]]
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]))
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.args = APP_ARGS
@ -318,7 +358,9 @@ def init():
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):
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:
sys.stderr.write("Error: The database couldn't be initialized.\n%s\n" % e)
try:
@ -687,7 +729,7 @@ def createcachetable(tablename):
table_output = []
index_output = []
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 ""))
if f.unique:
field_output.append("UNIQUE")
@ -695,9 +737,11 @@ def createcachetable(tablename):
field_output.append("PRIMARY KEY")
if f.db_index:
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))
full_statement = ["CREATE TABLE %s (" % tablename]
full_statement = ["CREATE TABLE %s (" % db.db.quote_name(tablename)]
for i, line in enumerate(table_output):
full_statement.append(' %s%s' % (line, i < len(table_output)-1 and ',' or ''))
full_statement.append(');')

View File

@ -57,14 +57,16 @@ def orderfield2column(f, opts):
return f
def orderlist2sql(order_list, opts, prefix=''):
if prefix.endswith('.'):
prefix = db.db.quote_name(prefix[:-1]) + '.'
output = []
for f in handle_legacy_orderlist(order_list):
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 == '?':
output.append(db.get_random_function_sql())
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)
def get_module(app_label, module_name):
@ -923,27 +925,31 @@ def method_save(opts, self):
record_exists = True
if pk_set:
# 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 cursor.fetchone():
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,
','.join(['%s=%%s' % f.column for f in non_pks]), opts.pk.attname),
cursor.execute("UPDATE %s SET %s WHERE %s=%%s" % \
(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])
else:
record_exists = False
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)
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:
field_names.append('_order')
field_names.append(db.db.quote_name('_order'))
# TODO: This assumes the database supports subqueries.
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))
cursor.execute("INSERT INTO %s (%s) VALUES (%s)" % (opts.db_table,
','.join(field_names), ','.join(placeholders)), db_values)
cursor.execute("INSERT INTO %s (%s) VALUES (%s)" % \
(db.db.quote_name(opts.db_table), ','.join(field_names),
','.join(placeholders)), db_values)
if opts.has_auto_field:
setattr(self, opts.pk.attname, db.get_last_insert_id(cursor, opts.db_table, opts.pk.column))
db.db.commit()
@ -970,12 +976,17 @@ def method_delete(opts, self):
for sub_obj in getattr(self, 'get_%s_list' % rel_opts_name)():
sub_obj.delete()
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),
self._meta.object_name.lower()), [getattr(self, opts.pk.attname)])
cursor.execute("DELETE FROM %s WHERE %s=%%s" % \
(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:
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" % (opts.db_table, opts.pk.column), [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)])
db.db.commit()
setattr(self, opts.pk.attname, None)
for f in opts.fields:
@ -992,16 +1003,20 @@ def method_delete(opts, self):
def method_get_next_in_order(opts, order_field, self):
if not hasattr(self, '_next_in_order_cache'):
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),
'%s=%%s' % order_field.column], limit=1,
where=['%s > (SELECT %s FROM %s WHERE %s=%%s)' % \
(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)])
return self._next_in_order_cache
def method_get_previous_in_order(opts, order_field, self):
if not hasattr(self, '_previous_in_order_cache'):
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),
'%s=%%s' % order_field.column], limit=1,
where=['%s < (SELECT %s FROM %s WHERE %s=%%s)' % \
(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)])
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
if not hasattr(self, cache_var):
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" % \
(','.join(['a.%s' % f.column for f in rel.fields]), rel.db_table,
field_with_rel.get_m2m_db_table(self._meta), rel.pk.column,
rel.object_name.lower(), self._meta.object_name.lower(), rel.get_order_sql('a'))
sql = "SELECT %s FROM %s a, %s b WHERE a.%s = b.%s AND b.%s = %%s %s" % \
(','.join(['a.%s' % db.db.quote_name(f.column) for f in rel.fields]),
db.db.quote_name(rel.db_table),
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.execute(sql, [getattr(self, self._meta.pk.attname)])
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()
this_id = getattr(self, self._meta.pk.attname)
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])
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])
db.db.commit()
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)
this_id = getattr(self, self._meta.pk.attname)
cursor = db.db.cursor()
cursor.execute("DELETE FROM %s WHERE %s_id = %%s" % (m2m_table, rel.object_name.lower()), [this_id])
sql = "INSERT INTO %s (%s_id, %s_id) VALUES (%%s, %%s)" % (m2m_table, rel.object_name.lower(), rel_opts.object_name.lower())
cursor.execute("DELETE FROM %s WHERE %s = %%s" % \
(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])
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):
cursor = db.db.cursor()
# 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)
cursor.executemany(sql, [(i, rel_val, j) for i, j in enumerate(id_list)])
db.db.commit()
@ -1121,7 +1153,11 @@ def method_set_order(ordered_obj, self, id_list):
def method_get_order(ordered_obj, self):
cursor = db.db.cursor()
# 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)
cursor.execute(sql, [rel_val])
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):
op = is_next and '>' or '<'
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))
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]
@ -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)
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:
return '%s%s %s %%s' % (table_prefix, field_name, db.OPERATOR_MAPPING[lookup_type])
except KeyError:
@ -1298,7 +1338,7 @@ def function_get_values_iterator(opts, klass, **kwargs):
cursor = db.db.cursor()
_, 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)
while 1:
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:
db_table = f.rel.to.db_table
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.
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
cache_tables_seen.append(db_table)
where.append('%s.%s = %s.%s' % (old_prefix, f.column, db_table, f.rel.get_related_field().column))
select.extend(['%s.%s' % (db_table, f2.column) for f2 in f.rel.to.fields])
where.append('%s.%s = %s.%s' % \
(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)
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...
for f in current_opts.many_to_many:
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
tables.append('%s %s' % (f.get_m2m_db_table(current_opts), rel_table_alias))
join_where.append('%s.%s = %s.%s_id' % (current_table_alias, current_opts.pk.column,
rel_table_alias, current_opts.object_name.lower()))
tables.append('%s %s' % \
(db.db.quote_name(f.get_m2m_db_table(current_opts)), rel_table_alias))
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
# don't have to do an extra join.
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
else:
new_table_alias = 't%s' % table_count
tables.append('%s %s' % (f.rel.to.db_table, new_table_alias))
join_where.append('%s.%s_id = %s.%s' % (rel_table_alias, f.rel.to.object_name.lower(),
new_table_alias, f.rel.to.pk.column))
tables.append('%s %s' % (db.db.quote_name(f.rel.to.db_table),
db.db.quote_name(new_table_alias)))
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
param_required = True
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))
else:
new_table_alias = 't%s' % table_count
tables.append('%s %s' % (f.rel.to.db_table, new_table_alias))
join_where.append('%s.%s = %s.%s' % (current_table_alias, f.column, \
new_table_alias, f.rel.to.pk.column))
tables.append('%s %s' % \
(db.db.quote_name(f.rel.to.db_table), db.db.quote_name(new_table_alias)))
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
param_required = True
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
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 = [db.db.quote_name(t) for t in tables]
where = kwargs.get('where') and kwargs['where'][:] 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.
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 = []
@ -1480,13 +1533,17 @@ def function_get_sql_clause(opts, **kwargs):
else:
col_name = f
order = "ASC"
# Use the database table as a column prefix if it wasn't given,
# 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', [])]:
table_prefix = opts.db_table + '.'
if "." in col_name:
table_prefix, col_name = col_name.split('.', 1)
table_prefix = db.db.quote_name(table_prefix) + '.'
else:
table_prefix = ''
order_by.append('%s%s %s' % (table_prefix, orderfield2column(col_name, opts), order))
# Use the database table as a column prefix if it wasn't given,
# 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', [])]:
table_prefix = db.db.quote_name(opts.db_table) + '.'
else:
table_prefix = ''
order_by.append('%s%s %s' % (table_prefix, db.db.quote_name(orderfield2column(col_name, opts)), order))
order_by = ", ".join(order_by)
# LIMIT and OFFSET clauses
@ -1501,7 +1558,7 @@ def function_get_sql_clause(opts, **kwargs):
def function_get_in_bulk(opts, klass, *args, **kwargs):
id_list = args and args[0] or kwargs['id_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
obj_list = function_get_list(opts, klass, **kwargs)
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'"
kwargs['order_by'] = [] # Clear this because it'll mess things up otherwise.
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)
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.execute(sql, params)
# 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'):
import sets
cursor = db.cursor()
cursor.execute("""
SELECT p.package, p.codename
FROM auth_permissions p, auth_groups_permissions gp, auth_users_groups ug
WHERE p.id = gp.permission_id
AND gp.group_id = ug.group_id
AND ug.user_id = %s""", [self.id])
# The SQL below works out to the following, after DB quoting:
# cursor.execute("""
# SELECT p.package, p.codename
# FROM auth_permissions p, auth_groups_permissions gp, auth_users_groups ug
# WHERE p.id = gp.permission_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()])
return self._group_perm_cache

View File

@ -62,11 +62,11 @@ class BlockTranslateNode(Node):
context.push()
for var,val in self.extra_context.items():
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:
count = resolve_variable_with_filters(self.counter, context)
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
else:
result = translation.gettext(singular) % context

View File

@ -27,6 +27,9 @@ from xml.parsers.expat import ExpatError
def rfc2822_date(date):
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):
"Creates a TagURI. See http://diveintomark.org/archives/2004/05/28/howto-atom-id"
tag = re.sub('^http://', '', url)
@ -38,7 +41,8 @@ def get_tag_uri(url, date):
class SyndicationFeed:
"Base class for all syndication feeds. Subclasses should provide write()"
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 = {
'title': title,
'link': link,
@ -49,11 +53,12 @@ class SyndicationFeed:
'author_link': author_link,
'subtitle': subtitle,
'categories': categories or (),
'feed_url': feed_url,
}
self.items = []
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=()):
"""
Adds an item to the feed. All args are expected to be Python Unicode
@ -66,6 +71,7 @@ class SyndicationFeed:
'description': description,
'author_email': author_email,
'author_name': author_name,
'author_link': author_link,
'pubdate': pubdate,
'comments': comments,
'unique_id': unique_id,
@ -187,9 +193,11 @@ class Atom1Feed(SyndicationFeed):
else:
handler.startElement(u"feed", {u"xmlns": self.ns})
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"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:
handler.startElement(u"author", {})
handler.addQuickElement(u"name", self.feed['author_name'])
@ -209,9 +217,9 @@ class Atom1Feed(SyndicationFeed):
for item in self.items:
handler.startElement(u"entry", {})
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:
handler.addQuickElement(u"updated", rfc2822_date(item['pubdate']).decode('ascii'))
handler.addQuickElement(u"updated", rfc3339_date(item['pubdate']).decode('ascii'))
# Author information.
if item['author_name'] is not None:
@ -219,6 +227,8 @@ class Atom1Feed(SyndicationFeed):
handler.addQuickElement(u"name", item['author_name'])
if item['author_email'] is not None:
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")
# 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
``OneToOneField``, takes an optional first positional argument -- a
human-readable name. If the human-readable name isn't given, Django will use
the machine-readable name, converting underscores to spaces.
human-readable name. If the human-readable name isn't given, Django will
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)
For ``ForeignKey``, ``ManyToManyField`` and ``OneToOneField``, use the
``verbose_name`` keyword argument::
In this example, the human-readable name is ``"first name"``::
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")
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,
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``
If ``True``, ``django-admin.py sqlindexes`` will output a ``CREATE INDEX``
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 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``
Names of extra exception subclasses to include in the generated module.
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"
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
level of magic pluralization would get confusing.
name, plus ``"s"``. This "poor man's pluralization" is intentional: Any
other level of magic pluralization would get confusing.
``order_with_respect_to``
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
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
---------------------------------------
@ -371,6 +386,55 @@ This example illustrates all possible attributes and methods for a ``Feed`` clas
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
# 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.
"""
# 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
# 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:
``__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
(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',
'ordering', 'lookup', 'get_latest', 'm2m_intermediary', 'one_to_one',
'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]
"""