mirror of
https://github.com/django/django.git
synced 2025-07-04 17:59:13 +00:00
sqlalchemy: Merged revisions 3832 to 3917 from trunk.
git-svn-id: http://code.djangoproject.com/svn/django/branches/sqlalchemy@3918 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
1bb4fa2cb6
commit
0b059aa4ea
8
AUTHORS
8
AUTHORS
@ -64,6 +64,7 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
Ian Clelland <clelland@gmail.com>
|
Ian Clelland <clelland@gmail.com>
|
||||||
crankycoder@gmail.com
|
crankycoder@gmail.com
|
||||||
Matt Croydon <http://www.postneo.com/>
|
Matt Croydon <http://www.postneo.com/>
|
||||||
|
dackze+django@gmail.com
|
||||||
Jonathan Daugherty (cygnus) <http://www.cprogrammer.org/>
|
Jonathan Daugherty (cygnus) <http://www.cprogrammer.org/>
|
||||||
Jason Davies (Esaj) <http://www.jasondavies.com/>
|
Jason Davies (Esaj) <http://www.jasondavies.com/>
|
||||||
Alex Dedul
|
Alex Dedul
|
||||||
@ -74,6 +75,7 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
Jeremy Dunck <http://dunck.us/>
|
Jeremy Dunck <http://dunck.us/>
|
||||||
Andy Dustman <farcepest@gmail.com>
|
Andy Dustman <farcepest@gmail.com>
|
||||||
Clint Ecker
|
Clint Ecker
|
||||||
|
Enrico <rico.bl@gmail.com>
|
||||||
favo@exoweb.net
|
favo@exoweb.net
|
||||||
gandalf@owca.info
|
gandalf@owca.info
|
||||||
Baishampayan Ghose
|
Baishampayan Ghose
|
||||||
@ -82,6 +84,7 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
Espen Grindhaug <http://grindhaug.org/>
|
Espen Grindhaug <http://grindhaug.org/>
|
||||||
Brant Harris
|
Brant Harris
|
||||||
heckj@mac.com
|
heckj@mac.com
|
||||||
|
Joel Heenan <joelh-django@planetjoel.com>
|
||||||
hipertracker@gmail.com
|
hipertracker@gmail.com
|
||||||
Ian Holsman <http://feh.holsman.net/>
|
Ian Holsman <http://feh.holsman.net/>
|
||||||
Kieran Holland <http://www.kieranholland.com>
|
Kieran Holland <http://www.kieranholland.com>
|
||||||
@ -95,6 +98,7 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
kilian <kilian.cavalotti@lip6.fr>
|
kilian <kilian.cavalotti@lip6.fr>
|
||||||
Sune Kirkeby <http://ibofobi.dk/>
|
Sune Kirkeby <http://ibofobi.dk/>
|
||||||
Cameron Knight (ckknight)
|
Cameron Knight (ckknight)
|
||||||
|
Meir Kriheli <http://mksoft.co.il/>
|
||||||
Bruce Kroeze <http://coderseye.com/>
|
Bruce Kroeze <http://coderseye.com/>
|
||||||
Joseph Kocherhans
|
Joseph Kocherhans
|
||||||
konrad@gwu.edu
|
konrad@gwu.edu
|
||||||
@ -103,7 +107,9 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
Eugene Lazutkin <http://lazutkin.com/blog/>
|
Eugene Lazutkin <http://lazutkin.com/blog/>
|
||||||
Jeong-Min Lee
|
Jeong-Min Lee
|
||||||
Christopher Lenz <http://www.cmlenz.net/>
|
Christopher Lenz <http://www.cmlenz.net/>
|
||||||
|
lerouxb@gmail.com
|
||||||
limodou
|
limodou
|
||||||
|
mattmcc
|
||||||
Martin Maney <http://www.chipy.org/Martin_Maney>
|
Martin Maney <http://www.chipy.org/Martin_Maney>
|
||||||
Manuzhai
|
Manuzhai
|
||||||
Petar Marić
|
Petar Marić
|
||||||
@ -115,6 +121,7 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
Eric Moritz <http://eric.themoritzfamily.com/>
|
Eric Moritz <http://eric.themoritzfamily.com/>
|
||||||
Robin Munn <http://www.geekforgod.com/>
|
Robin Munn <http://www.geekforgod.com/>
|
||||||
Nebojša Dorđević
|
Nebojša Dorđević
|
||||||
|
Fraser Nevett <mail@nevett.org>
|
||||||
Sam Newman <http://www.magpiebrain.com/>
|
Sam Newman <http://www.magpiebrain.com/>
|
||||||
Neal Norwitz <nnorwitz@google.com>
|
Neal Norwitz <nnorwitz@google.com>
|
||||||
oggie rob <oz.robharvey@gmail.com>
|
oggie rob <oz.robharvey@gmail.com>
|
||||||
@ -142,6 +149,7 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
Radek Švarz <http://www.svarz.cz/translate/>
|
Radek Švarz <http://www.svarz.cz/translate/>
|
||||||
Swaroop C H <http://www.swaroopch.info>
|
Swaroop C H <http://www.swaroopch.info>
|
||||||
Aaron Swartz <http://www.aaronsw.com/>
|
Aaron Swartz <http://www.aaronsw.com/>
|
||||||
|
Tyson Tate <tyson@fallingbullets.com>
|
||||||
Tom Tobin
|
Tom Tobin
|
||||||
Tom Insam
|
Tom Insam
|
||||||
Joe Topjian <http://joe.terrarum.net/geek/code/python/django/>
|
Joe Topjian <http://joe.terrarum.net/geek/code/python/django/>
|
||||||
|
8
MANIFEST.in
Normal file
8
MANIFEST.in
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
include AUTHORS
|
||||||
|
include INSTALL
|
||||||
|
include LICENSE
|
||||||
|
recursive-include django/conf/locale *
|
||||||
|
recursive-include django/contrib/admin/templates
|
||||||
|
recursive-include django/contrib/admin/media
|
||||||
|
recursive-include django/contrib/comments/templates
|
||||||
|
recursive-include django/contrib/sitemaps/templates
|
@ -1,16 +1,17 @@
|
|||||||
"Daily cleanup file"
|
"""
|
||||||
|
Daily cleanup job.
|
||||||
|
|
||||||
|
Can be run as a cronjob to clean out old data from the database (only expired
|
||||||
|
sessions at the moment).
|
||||||
|
"""
|
||||||
|
|
||||||
from django.db import backend, connection, transaction
|
from django.db import backend, connection, transaction
|
||||||
|
|
||||||
DOCUMENTATION_DIRECTORY = '/home/html/documentation/'
|
|
||||||
|
|
||||||
def clean_up():
|
def clean_up():
|
||||||
# Clean up old database records
|
# Clean up old database records
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
cursor.execute("DELETE FROM %s WHERE %s < NOW()" % \
|
cursor.execute("DELETE FROM %s WHERE %s < NOW()" % \
|
||||||
(backend.quote_name('core_sessions'), backend.quote_name('expire_date')))
|
(backend.quote_name('django_session'), backend.quote_name('expire_date')))
|
||||||
cursor.execute("DELETE FROM %s WHERE %s < NOW() - INTERVAL '1 week'" % \
|
|
||||||
(backend.quote_name('registration_challenges'), backend.quote_name('request_date')))
|
|
||||||
transaction.commit_unless_managed()
|
transaction.commit_unless_managed()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
@ -56,6 +56,7 @@ LANGUAGES = (
|
|||||||
('ja', gettext_noop('Japanese')),
|
('ja', gettext_noop('Japanese')),
|
||||||
('nl', gettext_noop('Dutch')),
|
('nl', gettext_noop('Dutch')),
|
||||||
('no', gettext_noop('Norwegian')),
|
('no', gettext_noop('Norwegian')),
|
||||||
|
('pl', gettext_noop('Polish')),
|
||||||
('pt-br', gettext_noop('Brazilian')),
|
('pt-br', gettext_noop('Brazilian')),
|
||||||
('ro', gettext_noop('Romanian')),
|
('ro', gettext_noop('Romanian')),
|
||||||
('ru', gettext_noop('Russian')),
|
('ru', gettext_noop('Russian')),
|
||||||
@ -223,10 +224,6 @@ YEAR_MONTH_FORMAT = 'F Y'
|
|||||||
# http://www.djangoproject.com/documentation/templates/#now
|
# http://www.djangoproject.com/documentation/templates/#now
|
||||||
MONTH_DAY_FORMAT = 'F j'
|
MONTH_DAY_FORMAT = 'F j'
|
||||||
|
|
||||||
# Whether to enable Psyco, which optimizes Python code. Requires Psyco.
|
|
||||||
# http://psyco.sourceforge.net/
|
|
||||||
ENABLE_PSYCO = False
|
|
||||||
|
|
||||||
# Do you want to manage transactions manually?
|
# Do you want to manage transactions manually?
|
||||||
# Hint: you really don't!
|
# Hint: you really don't!
|
||||||
TRANSACTIONS_MANAGED = False
|
TRANSACTIONS_MANAGED = False
|
||||||
@ -274,8 +271,8 @@ CACHE_MIDDLEWARE_KEY_PREFIX = ''
|
|||||||
COMMENTS_ALLOW_PROFANITIES = False
|
COMMENTS_ALLOW_PROFANITIES = False
|
||||||
|
|
||||||
# The profanities that will trigger a validation error in the
|
# The profanities that will trigger a validation error in the
|
||||||
# 'hasNoProfanities' validator. All of these should be in lower-case.
|
# 'hasNoProfanities' validator. All of these should be in lowercase.
|
||||||
PROFANITIES_LIST = ['asshat', 'asshead', 'asshole', 'cunt', 'fuck', 'gook', 'nigger', 'shit']
|
PROFANITIES_LIST = ('asshat', 'asshead', 'asshole', 'cunt', 'fuck', 'gook', 'nigger', 'shit')
|
||||||
|
|
||||||
# The group ID that designates which users are banned.
|
# The group ID that designates which users are banned.
|
||||||
# Set to None if you're not using it.
|
# Set to None if you're not using it.
|
||||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -7,8 +7,8 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Django 1.0\n"
|
"Project-Id-Version: Django 1.0\n"
|
||||||
"Report-Msgid-Bugs-To: Django-users Japan <django-ja@googlegroups.com>\n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2006-05-02 23:06+0900\n"
|
"POT-Creation-Date: 2006-10-06 00:30+0900\n"
|
||||||
"PO-Revision-Date: 2006-05-08 13:39+0900\n"
|
"PO-Revision-Date: 2006-05-08 13:39+0900\n"
|
||||||
"Last-Translator: makoto tsuyuki <mtsuyuki@gmail.com>\n"
|
"Last-Translator: makoto tsuyuki <mtsuyuki@gmail.com>\n"
|
||||||
"Language-Team: Japanese <django-ja@googlegroups.com>\n"
|
"Language-Team: Japanese <django-ja@googlegroups.com>\n"
|
||||||
@ -61,50 +61,58 @@ msgstr "選択してクリック"
|
|||||||
msgid "Clear all"
|
msgid "Clear all"
|
||||||
msgstr "全てクリア"
|
msgstr "全てクリア"
|
||||||
|
|
||||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45
|
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:34
|
||||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80
|
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:72
|
||||||
|
msgid "Show"
|
||||||
|
msgstr "表示"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:63
|
||||||
|
msgid "Hide"
|
||||||
|
msgstr "非表示"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:47
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
|
||||||
msgid "Now"
|
msgid "Now"
|
||||||
msgstr "現在"
|
msgstr "現在"
|
||||||
|
|
||||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:48
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:51
|
||||||
msgid "Clock"
|
msgid "Clock"
|
||||||
msgstr "時計"
|
msgstr "時計"
|
||||||
|
|
||||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:77
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:78
|
||||||
msgid "Choose a time"
|
msgid "Choose a time"
|
||||||
msgstr "時間を選択"
|
msgstr "時間を選択"
|
||||||
|
|
||||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
|
||||||
msgid "Midnight"
|
msgid "Midnight"
|
||||||
msgstr "夜中"
|
msgstr "夜中"
|
||||||
|
|
||||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
|
||||||
msgid "6 a.m."
|
msgid "6 a.m."
|
||||||
msgstr "午前 6 時"
|
msgstr "午前 6 時"
|
||||||
|
|
||||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:84
|
||||||
msgid "Noon"
|
msgid "Noon"
|
||||||
msgstr "正午"
|
msgstr "正午"
|
||||||
|
|
||||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:87
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:88
|
||||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:168
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
|
||||||
msgid "Cancel"
|
msgid "Cancel"
|
||||||
msgstr "キャンセル"
|
msgstr "キャンセル"
|
||||||
|
|
||||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:111
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:128
|
||||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:162
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:177
|
||||||
msgid "Today"
|
msgid "Today"
|
||||||
msgstr "今日"
|
msgstr "今日"
|
||||||
|
|
||||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:114
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:132
|
||||||
msgid "Calendar"
|
msgid "Calendar"
|
||||||
msgstr "カレンダー"
|
msgstr "カレンダー"
|
||||||
|
|
||||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:160
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:175
|
||||||
msgid "Yesterday"
|
msgid "Yesterday"
|
||||||
msgstr "昨日"
|
msgstr "昨日"
|
||||||
|
|
||||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
|
||||||
msgid "Tomorrow"
|
msgid "Tomorrow"
|
||||||
msgstr "明日"
|
msgstr "明日"
|
||||||
|
|
||||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
BIN
django/conf/locale/tr/LC_MESSAGES/djangojs.mo
Normal file
BIN
django/conf/locale/tr/LC_MESSAGES/djangojs.mo
Normal file
Binary file not shown.
109
django/conf/locale/tr/LC_MESSAGES/djangojs.po
Normal file
109
django/conf/locale/tr/LC_MESSAGES/djangojs.po
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
# Django 0.95
|
||||||
|
# Copyright (C) 2006 Django
|
||||||
|
# This file is distributed under the same license as the Django package.
|
||||||
|
# Bahadır Kandemir <bahadir@pardus.org.tr>, 2006.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Django 0.95\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2006-09-30 01:31+0300\n"
|
||||||
|
"PO-Revision-Date: 2006-09-30 01:31+0300\n"
|
||||||
|
"Last-Translator: Bahadır Kandemir <bahadir@pardus.org.tr>\n"
|
||||||
|
"Language-Team: Bahadır Kandemir <bahadir@pardus.org.tr>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:33
|
||||||
|
#, perl-format
|
||||||
|
msgid "Available %s"
|
||||||
|
msgstr "Mevcut %s"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:41
|
||||||
|
msgid "Choose all"
|
||||||
|
msgstr "Hepsini seç"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:46
|
||||||
|
msgid "Add"
|
||||||
|
msgstr "Ekle"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:48
|
||||||
|
msgid "Remove"
|
||||||
|
msgstr "Kaldır"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:53
|
||||||
|
#, perl-format
|
||||||
|
msgid "Chosen %s"
|
||||||
|
msgstr "Seçilen %s"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:54
|
||||||
|
msgid "Select your choice(s) and click "
|
||||||
|
msgstr "Seçiminizi yapın ve tıklayın "
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:59
|
||||||
|
msgid "Clear all"
|
||||||
|
msgstr "Hepsini temizle"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/dateparse.js:26
|
||||||
|
#: contrib/admin/media/js/calendar.js:24
|
||||||
|
msgid ""
|
||||||
|
"January February March April May June July August September October November "
|
||||||
|
"December"
|
||||||
|
msgstr "Ocak Şubat Mart Nisan Mayıs Haziran Temmuz Ağustos Eylül Ekim Kasım "
|
||||||
|
"Aralık"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/dateparse.js:27
|
||||||
|
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
|
||||||
|
msgstr "Pazar Pazartesi Salı Çarşamba Perşembe Cuma Cumartesi"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/calendar.js:25
|
||||||
|
msgid "S M T W T F S"
|
||||||
|
msgstr "P P S Ç P C C"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80
|
||||||
|
msgid "Now"
|
||||||
|
msgstr "Şimdi"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:48
|
||||||
|
msgid "Clock"
|
||||||
|
msgstr "Saat"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:77
|
||||||
|
msgid "Choose a time"
|
||||||
|
msgstr "Saat seçin"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
|
||||||
|
msgid "Midnight"
|
||||||
|
msgstr "Geceyarısı"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
|
||||||
|
msgid "6 a.m."
|
||||||
|
msgstr "Sabah 6"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
|
||||||
|
msgid "Noon"
|
||||||
|
msgstr "Öğle"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:87
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:168
|
||||||
|
msgid "Cancel"
|
||||||
|
msgstr "İptal"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:111
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:162
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "Bugün"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:114
|
||||||
|
msgid "Calendar"
|
||||||
|
msgstr "Takvim"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:160
|
||||||
|
msgid "Yesterday"
|
||||||
|
msgstr "Dün"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164
|
||||||
|
msgid "Tomorrow"
|
||||||
|
msgstr "Yarın"
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
<h1>{{ name }}</h1>
|
<h1>{{ name }}</h1>
|
||||||
|
|
||||||
<h2 class="subhead">{{ summary|escape }}</h2>
|
<h2 class="subhead">{{ summary }}</h2>
|
||||||
|
|
||||||
<p>{{ body }}</p>
|
<p>{{ body }}</p>
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ def staff_member_required(view_func):
|
|||||||
|
|
||||||
# The user data is correct; log in the user in and continue.
|
# The user data is correct; log in the user in and continue.
|
||||||
else:
|
else:
|
||||||
if user.is_staff:
|
if user.is_active and user.is_staff:
|
||||||
login(request, user)
|
login(request, user)
|
||||||
# TODO: set last_login with an event.
|
# TODO: set last_login with an event.
|
||||||
user.last_login = datetime.datetime.now()
|
user.last_login = datetime.datetime.now()
|
||||||
|
@ -46,6 +46,7 @@ def createsuperuser(username=None, email=None, password=None):
|
|||||||
if not username.isalnum():
|
if not username.isalnum():
|
||||||
sys.stderr.write("Error: That username is invalid. Use only letters, digits and underscores.\n")
|
sys.stderr.write("Error: That username is invalid. Use only letters, digits and underscores.\n")
|
||||||
username = None
|
username = None
|
||||||
|
continue
|
||||||
try:
|
try:
|
||||||
User.objects.get(username=username)
|
User.objects.get(username=username)
|
||||||
except User.DoesNotExist:
|
except User.DoesNotExist:
|
||||||
|
@ -29,8 +29,8 @@ login_required.__doc__ = (
|
|||||||
|
|
||||||
def permission_required(perm, login_url=LOGIN_URL):
|
def permission_required(perm, login_url=LOGIN_URL):
|
||||||
"""
|
"""
|
||||||
Decorator for views that checks if a user has a particular permission
|
Decorator for views that checks whether a user has a particular permission
|
||||||
enabled, redirectiing to the log-in page if necessary.
|
enabled, redirecting to the log-in page if necessary.
|
||||||
"""
|
"""
|
||||||
return user_passes_test(lambda u: u.has_perm(perm), login_url=login_url)
|
return user_passes_test(lambda u: u.has_perm(perm), login_url=login_url)
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ class UserCreationForm(forms.Manipulator):
|
|||||||
validator_list=[validators.isAlphaNumeric, self.isValidUsername]),
|
validator_list=[validators.isAlphaNumeric, self.isValidUsername]),
|
||||||
forms.PasswordField(field_name='password1', length=30, maxlength=60, is_required=True),
|
forms.PasswordField(field_name='password1', length=30, maxlength=60, is_required=True),
|
||||||
forms.PasswordField(field_name='password2', length=30, maxlength=60, is_required=True,
|
forms.PasswordField(field_name='password2', length=30, maxlength=60, is_required=True,
|
||||||
validator_list=[validators.AlwaysMatchesOtherField('password1', "The two password fields didn't match.")]),
|
validator_list=[validators.AlwaysMatchesOtherField('password1', _("The two password fields didn't match."))]),
|
||||||
)
|
)
|
||||||
|
|
||||||
def isValidUsername(self, field_data, all_data):
|
def isValidUsername(self, field_data, all_data):
|
||||||
@ -21,7 +21,7 @@ class UserCreationForm(forms.Manipulator):
|
|||||||
User.objects.get(username=field_data)
|
User.objects.get(username=field_data)
|
||||||
except User.DoesNotExist:
|
except User.DoesNotExist:
|
||||||
return
|
return
|
||||||
raise validators.ValidationError, 'A user with that username already exists.'
|
raise validators.ValidationError, _('A user with that username already exists.')
|
||||||
|
|
||||||
def save(self, new_data):
|
def save(self, new_data):
|
||||||
"Creates the user."
|
"Creates the user."
|
||||||
@ -81,7 +81,7 @@ class PasswordResetForm(forms.Manipulator):
|
|||||||
try:
|
try:
|
||||||
self.user_cache = User.objects.get(email__iexact=new_data)
|
self.user_cache = User.objects.get(email__iexact=new_data)
|
||||||
except User.DoesNotExist:
|
except User.DoesNotExist:
|
||||||
raise validators.ValidationError, _("That e-mail address doesn't have an associated user acount. Are you sure you've registered?")
|
raise validators.ValidationError, _("That e-mail address doesn't have an associated user account. Are you sure you've registered?")
|
||||||
|
|
||||||
def save(self, domain_override=None, email_template_name='registration/password_reset_email.html'):
|
def save(self, domain_override=None, email_template_name='registration/password_reset_email.html'):
|
||||||
"Calculates a new password randomly and sends it to the user"
|
"Calculates a new password randomly and sends it to the user"
|
||||||
|
@ -216,6 +216,8 @@ class User(models.Model):
|
|||||||
|
|
||||||
def has_module_perms(self, app_label):
|
def has_module_perms(self, app_label):
|
||||||
"Returns True if the user has any permissions in the given app label."
|
"Returns True if the user has any permissions in the given app label."
|
||||||
|
if not self.is_active:
|
||||||
|
return False
|
||||||
if self.is_superuser:
|
if self.is_superuser:
|
||||||
return True
|
return True
|
||||||
return bool(len([p for p in self.get_all_permissions() if p[:p.index('.')] == app_label]))
|
return bool(len([p for p in self.get_all_permissions() if p[:p.index('.')] == app_label]))
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<urlset xmlns="http://www.google.com/schemas/sitemap/0.84">
|
<urlset xmlns="http://www.google.com/schemas/sitemap/0.84">
|
||||||
|
{% spaceless %}
|
||||||
{% for url in urlset %}
|
{% for url in urlset %}
|
||||||
<url>
|
<url>
|
||||||
<loc>{{ url.location|escape }}</loc>
|
<loc>{{ url.location|escape }}</loc>
|
||||||
@ -8,4 +9,5 @@
|
|||||||
{% if url.priority %}<priority>{{ url.priority }}</priority>{% endif %}
|
{% if url.priority %}<priority>{{ url.priority }}</priority>{% endif %}
|
||||||
</url>
|
</url>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
{% endspaceless %}
|
||||||
</urlset>
|
</urlset>
|
||||||
|
@ -1,8 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<sitemapindex xmlns="http://www.google.com/schemas/sitemap/0.84">
|
<sitemapindex xmlns="http://www.google.com/schemas/sitemap/0.84">
|
||||||
{% for location in sitemaps %}
|
{% for location in sitemaps %}<sitemap><loc>{{ location|escape }}</loc></sitemap>{% endfor %}
|
||||||
<sitemap>
|
|
||||||
<loc>{{ location|escape }}</loc>
|
|
||||||
</sitemap>
|
|
||||||
{% endfor %}
|
|
||||||
</sitemapindex>
|
</sitemapindex>
|
||||||
|
@ -48,7 +48,7 @@ class BaseHandler(object):
|
|||||||
if hasattr(mw_instance, 'process_exception'):
|
if hasattr(mw_instance, 'process_exception'):
|
||||||
self._exception_middleware.insert(0, mw_instance.process_exception)
|
self._exception_middleware.insert(0, mw_instance.process_exception)
|
||||||
|
|
||||||
def get_response(self, path, request):
|
def get_response(self, request):
|
||||||
"Returns an HttpResponse object for the given HttpRequest"
|
"Returns an HttpResponse object for the given HttpRequest"
|
||||||
from django.core import exceptions, urlresolvers
|
from django.core import exceptions, urlresolvers
|
||||||
from django.core.mail import mail_admins
|
from django.core.mail import mail_admins
|
||||||
@ -62,7 +62,7 @@ class BaseHandler(object):
|
|||||||
|
|
||||||
resolver = urlresolvers.RegexURLResolver(r'^/', settings.ROOT_URLCONF)
|
resolver = urlresolvers.RegexURLResolver(r'^/', settings.ROOT_URLCONF)
|
||||||
try:
|
try:
|
||||||
callback, callback_args, callback_kwargs = resolver.resolve(path)
|
callback, callback_args, callback_kwargs = resolver.resolve(request.path)
|
||||||
|
|
||||||
# Apply view middleware
|
# Apply view middleware
|
||||||
for middleware_method in self._view_middleware:
|
for middleware_method in self._view_middleware:
|
||||||
@ -89,7 +89,8 @@ class BaseHandler(object):
|
|||||||
return response
|
return response
|
||||||
except http.Http404, e:
|
except http.Http404, e:
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
return self.get_technical_error_response(request, is404=True, exception=e)
|
from django.views import debug
|
||||||
|
return debug.technical_404_response(request, e)
|
||||||
else:
|
else:
|
||||||
callback, param_dict = resolver.resolve404()
|
callback, param_dict = resolver.resolve404()
|
||||||
return callback(request, **param_dict)
|
return callback(request, **param_dict)
|
||||||
@ -99,39 +100,23 @@ class BaseHandler(object):
|
|||||||
pass # See http://code.djangoproject.com/ticket/1023
|
pass # See http://code.djangoproject.com/ticket/1023
|
||||||
except: # Handle everything else, including SuspiciousOperation, etc.
|
except: # Handle everything else, including SuspiciousOperation, etc.
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
return self.get_technical_error_response(request)
|
from django.views import debug
|
||||||
|
return debug.technical_500_response(request, *sys.exc_info())
|
||||||
else:
|
else:
|
||||||
# Get the exception info now, in case another exception is thrown later.
|
# Get the exception info now, in case another exception is thrown later.
|
||||||
exc_info = sys.exc_info()
|
exc_info = sys.exc_info()
|
||||||
receivers = dispatcher.send(signal=signals.got_request_exception)
|
receivers = dispatcher.send(signal=signals.got_request_exception)
|
||||||
# When DEBUG is False, send an error message to the admins.
|
# When DEBUG is False, send an error message to the admins.
|
||||||
subject = 'Error (%s IP): %s' % ((request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS and 'internal' or 'EXTERNAL'), getattr(request, 'path', ''))
|
subject = 'Error (%s IP): %s' % ((request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS and 'internal' or 'EXTERNAL'), request.path)
|
||||||
try:
|
try:
|
||||||
request_repr = repr(request)
|
request_repr = repr(request)
|
||||||
except:
|
except:
|
||||||
request_repr = "Request repr() unavailable"
|
request_repr = "Request repr() unavailable"
|
||||||
message = "%s\n\n%s" % (self._get_traceback(exc_info), request_repr)
|
message = "%s\n\n%s" % (self._get_traceback(exc_info), request_repr)
|
||||||
mail_admins(subject, message, fail_silently=True)
|
mail_admins(subject, message, fail_silently=True)
|
||||||
return self.get_friendly_error_response(request, resolver)
|
# Return an HttpResponse that displays a friendly error message.
|
||||||
|
callback, param_dict = resolver.resolve500()
|
||||||
def get_friendly_error_response(self, request, resolver):
|
return callback(request, **param_dict)
|
||||||
"""
|
|
||||||
Returns an HttpResponse that displays a PUBLIC error message for a
|
|
||||||
fundamental error.
|
|
||||||
"""
|
|
||||||
callback, param_dict = resolver.resolve500()
|
|
||||||
return callback(request, **param_dict)
|
|
||||||
|
|
||||||
def get_technical_error_response(self, request, is404=False, exception=None):
|
|
||||||
"""
|
|
||||||
Returns an HttpResponse that displays a TECHNICAL error message for a
|
|
||||||
fundamental error.
|
|
||||||
"""
|
|
||||||
from django.views import debug
|
|
||||||
if is404:
|
|
||||||
return debug.technical_404_response(request, exception)
|
|
||||||
else:
|
|
||||||
return debug.technical_500_response(request, *sys.exc_info())
|
|
||||||
|
|
||||||
def _get_traceback(self, exc_info=None):
|
def _get_traceback(self, exc_info=None):
|
||||||
"Helper function to return the traceback as a string"
|
"Helper function to return the traceback as a string"
|
||||||
|
@ -102,7 +102,7 @@ class ModPythonRequest(http.HttpRequest):
|
|||||||
'REQUEST_METHOD': self._req.method,
|
'REQUEST_METHOD': self._req.method,
|
||||||
'SCRIPT_NAME': None, # Not supported
|
'SCRIPT_NAME': None, # Not supported
|
||||||
'SERVER_NAME': self._req.server.server_hostname,
|
'SERVER_NAME': self._req.server.server_hostname,
|
||||||
'SERVER_PORT': self._req.server.port,
|
'SERVER_PORT': str(self._req.connection.local_addr[1]),
|
||||||
'SERVER_PROTOCOL': self._req.protocol,
|
'SERVER_PROTOCOL': self._req.protocol,
|
||||||
'SERVER_SOFTWARE': 'mod_python'
|
'SERVER_SOFTWARE': 'mod_python'
|
||||||
}
|
}
|
||||||
@ -139,10 +139,6 @@ class ModPythonHandler(BaseHandler):
|
|||||||
# that use settings now can work
|
# that use settings now can work
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
if settings.ENABLE_PSYCO:
|
|
||||||
import psyco
|
|
||||||
psyco.profile()
|
|
||||||
|
|
||||||
# if we need to set up middleware, now that settings works we can do it now.
|
# if we need to set up middleware, now that settings works we can do it now.
|
||||||
if self._request_middleware is None:
|
if self._request_middleware is None:
|
||||||
self.load_middleware()
|
self.load_middleware()
|
||||||
@ -150,7 +146,7 @@ class ModPythonHandler(BaseHandler):
|
|||||||
dispatcher.send(signal=signals.request_started)
|
dispatcher.send(signal=signals.request_started)
|
||||||
try:
|
try:
|
||||||
request = ModPythonRequest(req)
|
request = ModPythonRequest(req)
|
||||||
response = self.get_response(req.uri, request)
|
response = self.get_response(request)
|
||||||
|
|
||||||
# Apply response middleware
|
# Apply response middleware
|
||||||
for middleware_method in self._response_middleware:
|
for middleware_method in self._response_middleware:
|
||||||
@ -160,23 +156,20 @@ class ModPythonHandler(BaseHandler):
|
|||||||
dispatcher.send(signal=signals.request_finished)
|
dispatcher.send(signal=signals.request_finished)
|
||||||
|
|
||||||
# Convert our custom HttpResponse object back into the mod_python req.
|
# Convert our custom HttpResponse object back into the mod_python req.
|
||||||
populate_apache_request(response, req)
|
req.content_type = response['Content-Type']
|
||||||
return 0 # mod_python.apache.OK
|
for key, value in response.headers.items():
|
||||||
|
if key != 'Content-Type':
|
||||||
|
req.headers_out[key] = value
|
||||||
|
for c in response.cookies.values():
|
||||||
|
req.headers_out.add('Set-Cookie', c.output(header=''))
|
||||||
|
req.status = response.status_code
|
||||||
|
try:
|
||||||
|
for chunk in response:
|
||||||
|
req.write(chunk)
|
||||||
|
finally:
|
||||||
|
response.close()
|
||||||
|
|
||||||
def populate_apache_request(http_response, mod_python_req):
|
return 0 # mod_python.apache.OK
|
||||||
"Populates the mod_python request object with an HttpResponse"
|
|
||||||
mod_python_req.content_type = http_response['Content-Type']
|
|
||||||
for key, value in http_response.headers.items():
|
|
||||||
if key != 'Content-Type':
|
|
||||||
mod_python_req.headers_out[key] = value
|
|
||||||
for c in http_response.cookies.values():
|
|
||||||
mod_python_req.headers_out.add('Set-Cookie', c.output(header=''))
|
|
||||||
mod_python_req.status = http_response.status_code
|
|
||||||
try:
|
|
||||||
for chunk in http_response:
|
|
||||||
mod_python_req.write(chunk)
|
|
||||||
finally:
|
|
||||||
http_response.close()
|
|
||||||
|
|
||||||
def handler(req):
|
def handler(req):
|
||||||
# mod_python hooks into this function.
|
# mod_python hooks into this function.
|
||||||
|
@ -174,10 +174,6 @@ class WSGIHandler(BaseHandler):
|
|||||||
def __call__(self, environ, start_response):
|
def __call__(self, environ, start_response):
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
if settings.ENABLE_PSYCO:
|
|
||||||
import psyco
|
|
||||||
psyco.profile()
|
|
||||||
|
|
||||||
# Set up middleware if needed. We couldn't do this earlier, because
|
# Set up middleware if needed. We couldn't do this earlier, because
|
||||||
# settings weren't available.
|
# settings weren't available.
|
||||||
if self._request_middleware is None:
|
if self._request_middleware is None:
|
||||||
@ -186,7 +182,7 @@ class WSGIHandler(BaseHandler):
|
|||||||
dispatcher.send(signal=signals.request_started)
|
dispatcher.send(signal=signals.request_started)
|
||||||
try:
|
try:
|
||||||
request = WSGIRequest(environ)
|
request = WSGIRequest(environ)
|
||||||
response = self.get_response(request.path, request)
|
response = self.get_response(request)
|
||||||
|
|
||||||
# Apply response middleware
|
# Apply response middleware
|
||||||
for middleware_method in self._response_middleware:
|
for middleware_method in self._response_middleware:
|
||||||
|
@ -103,7 +103,6 @@ def get_sql_create(app):
|
|||||||
known_models = set([model for model in _get_installed_models(_get_table_list()) if model not in app_models])
|
known_models = set([model for model in _get_installed_models(_get_table_list()) if model not in app_models])
|
||||||
pending_references = {}
|
pending_references = {}
|
||||||
|
|
||||||
|
|
||||||
for model in app_models:
|
for model in app_models:
|
||||||
output, references = _get_sql_model_create(model, known_models)
|
output, references = _get_sql_model_create(model, known_models)
|
||||||
final_output.extend(output)
|
final_output.extend(output)
|
||||||
@ -147,7 +146,7 @@ def _get_sql_model_create(model, known_models=set()):
|
|||||||
table_output = []
|
table_output = []
|
||||||
pending_references = {}
|
pending_references = {}
|
||||||
for f in opts.fields:
|
for f in opts.fields:
|
||||||
if isinstance(f, models.ForeignKey):
|
if isinstance(f, (models.ForeignKey, models.OneToOneField)):
|
||||||
rel_field = f.rel.get_related_field()
|
rel_field = f.rel.get_related_field()
|
||||||
data_type = get_rel_data_type(rel_field)
|
data_type = get_rel_data_type(rel_field)
|
||||||
else:
|
else:
|
||||||
@ -398,32 +397,39 @@ get_sql_sequence_reset.help_doc = "Prints the SQL statements for resetting Postg
|
|||||||
get_sql_sequence_reset.args = APP_ARGS
|
get_sql_sequence_reset.args = APP_ARGS
|
||||||
|
|
||||||
def get_sql_indexes(app):
|
def get_sql_indexes(app):
|
||||||
"Returns a list of the CREATE INDEX SQL statements for the given app."
|
"Returns a list of the CREATE INDEX SQL statements for all models in the given app."
|
||||||
from django.db import backend, models
|
from django.db import models
|
||||||
output = []
|
output = []
|
||||||
|
|
||||||
for model in models.get_models(app):
|
for model in models.get_models(app):
|
||||||
for f in model._meta.fields:
|
output.extend(get_sql_indexes_for_model(model))
|
||||||
if f.db_index:
|
|
||||||
unique = f.unique and 'UNIQUE ' or ''
|
|
||||||
output.append(
|
|
||||||
style.SQL_KEYWORD('CREATE %sINDEX' % unique) + ' ' + \
|
|
||||||
style.SQL_TABLE('%s_%s' % (model._meta.db_table, f.column)) + ' ' + \
|
|
||||||
style.SQL_KEYWORD('ON') + ' ' + \
|
|
||||||
style.SQL_TABLE(backend.quote_name(model._meta.db_table)) + ' ' + \
|
|
||||||
"(%s);" % style.SQL_FIELD(backend.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
|
||||||
|
|
||||||
|
def get_sql_indexes_for_model(model):
|
||||||
|
"Returns the CREATE INDEX SQL statements for a single model"
|
||||||
|
from django.db import backend
|
||||||
|
output = []
|
||||||
|
|
||||||
|
for f in model._meta.fields:
|
||||||
|
if f.db_index:
|
||||||
|
unique = f.unique and 'UNIQUE ' or ''
|
||||||
|
output.append(
|
||||||
|
style.SQL_KEYWORD('CREATE %sINDEX' % unique) + ' ' + \
|
||||||
|
style.SQL_TABLE('%s_%s' % (model._meta.db_table, f.column)) + ' ' + \
|
||||||
|
style.SQL_KEYWORD('ON') + ' ' + \
|
||||||
|
style.SQL_TABLE(backend.quote_name(model._meta.db_table)) + ' ' + \
|
||||||
|
"(%s);" % style.SQL_FIELD(backend.quote_name(f.column))
|
||||||
|
)
|
||||||
|
return output
|
||||||
|
|
||||||
def get_sql_all(app):
|
def get_sql_all(app):
|
||||||
"Returns a list of CREATE TABLE SQL, initial-data inserts, and CREATE INDEX SQL for the given module."
|
"Returns a list of CREATE TABLE SQL, initial-data inserts, and CREATE INDEX SQL for the given module."
|
||||||
return get_sql_create(app) + get_sql_initial_data(app) + get_sql_indexes(app)
|
return get_sql_create(app) + get_sql_initial_data(app) + get_sql_indexes(app)
|
||||||
get_sql_all.help_doc = "Prints the CREATE TABLE, initial-data and CREATE INDEX SQL statements for the given model module name(s)."
|
get_sql_all.help_doc = "Prints the CREATE TABLE, initial-data and CREATE INDEX SQL statements for the given model module name(s)."
|
||||||
get_sql_all.args = APP_ARGS
|
get_sql_all.args = APP_ARGS
|
||||||
|
|
||||||
def syncdb(verbosity=2, interactive=True):
|
def syncdb(verbosity=1, interactive=True):
|
||||||
"Creates the database tables for all apps in INSTALLED_APPS whose tables haven't already been created."
|
"Creates the database tables for all apps in INSTALLED_APPS whose tables haven't already been created."
|
||||||
from django.db import connection, transaction, models, get_creation_module
|
from django.db import connection, transaction, models, get_creation_module
|
||||||
from django.db.models import signals
|
from django.db.models import signals
|
||||||
@ -457,21 +463,21 @@ def syncdb(verbosity=2, interactive=True):
|
|||||||
pending_references = {}
|
pending_references = {}
|
||||||
|
|
||||||
for app in models.get_apps():
|
for app in models.get_apps():
|
||||||
|
app_name = app.__name__.split('.')[-2]
|
||||||
model_list = models.get_models(app)
|
model_list = models.get_models(app)
|
||||||
for model in model_list:
|
for model in model_list:
|
||||||
# Create the model's database table, if it doesn't already exist.
|
# Create the model's database table, if it doesn't already exist.
|
||||||
|
if verbosity >= 2:
|
||||||
|
print "Processing %s.%s model" % (app_name, model._meta.object_name)
|
||||||
if model._meta.db_table in table_list:
|
if model._meta.db_table in table_list:
|
||||||
continue
|
continue
|
||||||
sql, references = _get_sql_model_create(model, seen_models)
|
sql, references = _get_sql_model_create(model, seen_models)
|
||||||
seen_models.add(model)
|
seen_models.add(model)
|
||||||
created_models.add(model)
|
created_models.add(model)
|
||||||
for refto, refs in references.items():
|
for refto, refs in references.items():
|
||||||
try:
|
pending_references.setdefault(refto, []).extend(refs)
|
||||||
pending_references[refto].extend(refs)
|
|
||||||
except KeyError:
|
|
||||||
pending_references[refto] = refs
|
|
||||||
sql.extend(_get_sql_for_pending_references(model, pending_references))
|
sql.extend(_get_sql_for_pending_references(model, pending_references))
|
||||||
if verbosity >= 2:
|
if verbosity >= 1:
|
||||||
print "Creating table %s" % model._meta.db_table
|
print "Creating table %s" % model._meta.db_table
|
||||||
for statement in sql:
|
for statement in sql:
|
||||||
cursor.execute(statement)
|
cursor.execute(statement)
|
||||||
@ -482,7 +488,7 @@ def syncdb(verbosity=2, interactive=True):
|
|||||||
sql = _get_many_to_many_sql_for_model(model)
|
sql = _get_many_to_many_sql_for_model(model)
|
||||||
if sql:
|
if sql:
|
||||||
if verbosity >= 2:
|
if verbosity >= 2:
|
||||||
print "Creating many-to-many tables for %s model" % model.__name__
|
print "Creating many-to-many tables for %s.%s model" % (app_name, model._meta.object_name)
|
||||||
for statement in sql:
|
for statement in sql:
|
||||||
cursor.execute(statement)
|
cursor.execute(statement)
|
||||||
|
|
||||||
@ -491,6 +497,9 @@ def syncdb(verbosity=2, interactive=True):
|
|||||||
# Send the post_syncdb signal, so individual apps can do whatever they need
|
# Send the post_syncdb signal, so individual apps can do whatever they need
|
||||||
# to do at this point.
|
# to do at this point.
|
||||||
for app in models.get_apps():
|
for app in models.get_apps():
|
||||||
|
app_name = app.__name__.split('.')[-2]
|
||||||
|
if verbosity >= 2:
|
||||||
|
print "Running post-sync handlers for application", app_name
|
||||||
dispatcher.send(signal=signals.post_syncdb, sender=app,
|
dispatcher.send(signal=signals.post_syncdb, sender=app,
|
||||||
app=app, created_models=created_models,
|
app=app, created_models=created_models,
|
||||||
verbosity=verbosity, interactive=interactive)
|
verbosity=verbosity, interactive=interactive)
|
||||||
@ -501,14 +510,33 @@ def syncdb(verbosity=2, interactive=True):
|
|||||||
if model in created_models:
|
if model in created_models:
|
||||||
initial_sql = get_sql_initial_data_for_model(model)
|
initial_sql = get_sql_initial_data_for_model(model)
|
||||||
if initial_sql:
|
if initial_sql:
|
||||||
if verbosity >= 2:
|
if verbosity >= 1:
|
||||||
print "Installing initial data for %s model" % model._meta.object_name
|
print "Installing initial data for %s.%s model" % (app_name, model._meta.object_name)
|
||||||
try:
|
try:
|
||||||
for sql in initial_sql:
|
for sql in initial_sql:
|
||||||
cursor.execute(sql)
|
cursor.execute(sql)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
sys.stderr.write("Failed to install initial SQL data for %s model: %s" % \
|
sys.stderr.write("Failed to install initial SQL data for %s.%s model: %s" % \
|
||||||
(model._meta.object_name, e))
|
(app_name, model._meta.object_name, e))
|
||||||
|
transaction.rollback_unless_managed()
|
||||||
|
else:
|
||||||
|
transaction.commit_unless_managed()
|
||||||
|
|
||||||
|
# Install SQL indicies for all newly created models
|
||||||
|
for app in models.get_apps():
|
||||||
|
app_name = app.__name__.split('.')[-2]
|
||||||
|
for model in models.get_models(app):
|
||||||
|
if model in created_models:
|
||||||
|
index_sql = get_sql_indexes_for_model(model)
|
||||||
|
if index_sql:
|
||||||
|
if verbosity >= 1:
|
||||||
|
print "Installing index for %s.%s model" % (app_name, model._meta.object_name)
|
||||||
|
try:
|
||||||
|
for sql in index_sql:
|
||||||
|
cursor.execute(sql)
|
||||||
|
except Exception, e:
|
||||||
|
sys.stderr.write("Failed to install index for %s.%s model: %s" % \
|
||||||
|
(app_name, model._meta.object_name, e))
|
||||||
transaction.rollback_unless_managed()
|
transaction.rollback_unless_managed()
|
||||||
else:
|
else:
|
||||||
transaction.commit_unless_managed()
|
transaction.commit_unless_managed()
|
||||||
@ -596,7 +624,7 @@ The full error: """ % (app_name, app_name)) + style.ERROR_OUTPUT(str(e)) + '\n')
|
|||||||
install.help_doc = "Executes ``sqlall`` for the given app(s) in the current database."
|
install.help_doc = "Executes ``sqlall`` for the given app(s) in the current database."
|
||||||
install.args = APP_ARGS
|
install.args = APP_ARGS
|
||||||
|
|
||||||
def reset(app):
|
def reset(app, interactive=True):
|
||||||
"Executes the equivalent of 'get_sql_reset' in the current database."
|
"Executes the equivalent of 'get_sql_reset' in the current database."
|
||||||
from django.db import connection, transaction
|
from django.db import connection, transaction
|
||||||
app_name = app.__name__.split('.')[-2]
|
app_name = app.__name__.split('.')[-2]
|
||||||
@ -607,21 +635,25 @@ def reset(app):
|
|||||||
_check_for_validation_errors(app)
|
_check_for_validation_errors(app)
|
||||||
sql_list = get_sql_reset(app)
|
sql_list = get_sql_reset(app)
|
||||||
|
|
||||||
confirm = raw_input("""
|
if interactive:
|
||||||
|
confirm = raw_input("""
|
||||||
You have requested a database reset.
|
You have requested a database reset.
|
||||||
This will IRREVERSIBLY DESTROY any data in your database.
|
This will IRREVERSIBLY DESTROY any data in your database.
|
||||||
Are you sure you want to do this?
|
Are you sure you want to do this?
|
||||||
|
|
||||||
Type 'yes' to continue, or 'no' to cancel: """)
|
Type 'yes' to continue, or 'no' to cancel: """)
|
||||||
|
else:
|
||||||
|
confirm = 'yes'
|
||||||
|
|
||||||
if confirm == 'yes':
|
if confirm == 'yes':
|
||||||
try:
|
try:
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
for sql in sql_list:
|
for sql in sql_list:
|
||||||
cursor.execute(sql)
|
cursor.execute(sql)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
sys.stderr.write(style.ERROR("""Error: %s couldn't be installed. Possible reasons:
|
sys.stderr.write(style.ERROR("""Error: %s couldn't be reset. Possible reasons:
|
||||||
* The database isn't running or isn't configured correctly.
|
* The database isn't running or isn't configured correctly.
|
||||||
* At least one of the database tables already exists.
|
* At least one of the database tables doesn't exist.
|
||||||
* The SQL was invalid.
|
* The SQL was invalid.
|
||||||
Hint: Look at the output of 'django-admin.py sqlreset %s'. That's the SQL this command wasn't able to run.
|
Hint: Look at the output of 'django-admin.py sqlreset %s'. That's the SQL this command wasn't able to run.
|
||||||
The full error: """ % (app_name, app_name)) + style.ERROR_OUTPUT(str(e)) + '\n')
|
The full error: """ % (app_name, app_name)) + style.ERROR_OUTPUT(str(e)) + '\n')
|
||||||
@ -820,7 +852,8 @@ def get_validation_errors(outfile, app=None):
|
|||||||
validates all models of all installed apps. Writes errors, if any, to outfile.
|
validates all models of all installed apps. Writes errors, if any, to outfile.
|
||||||
Returns number of errors.
|
Returns number of errors.
|
||||||
"""
|
"""
|
||||||
from django.db import models
|
from django.conf import settings
|
||||||
|
from django.db import models, connection
|
||||||
from django.db.models.loading import get_app_errors
|
from django.db.models.loading import get_app_errors
|
||||||
from django.db.models.fields.related import RelatedObject
|
from django.db.models.fields.related import RelatedObject
|
||||||
|
|
||||||
@ -862,6 +895,12 @@ def get_validation_errors(outfile, app=None):
|
|||||||
if f.db_index not in (None, True, False):
|
if f.db_index not in (None, True, False):
|
||||||
e.add(opts, '"%s": "db_index" should be either None, True or False.' % f.name)
|
e.add(opts, '"%s": "db_index" should be either None, True or False.' % f.name)
|
||||||
|
|
||||||
|
# Check that maxlength <= 255 if using older MySQL versions.
|
||||||
|
if settings.DATABASE_ENGINE == 'mysql':
|
||||||
|
db_version = connection.get_server_version()
|
||||||
|
if db_version < (5, 0, 3) and isinstance(f, (models.CharField, models.CommaSeparatedIntegerField, models.SlugField)) and f.maxlength > 255:
|
||||||
|
e.add(opts, '"%s": %s cannot have a "maxlength" greater than 255 when you are using a version of MySQL prior to 5.0.3 (you are using %s).' % (f.name, f.__class__.__name__, '.'.join([str(n) for n in db_version[:3]])))
|
||||||
|
|
||||||
# Check to see if the related field will clash with any
|
# Check to see if the related field will clash with any
|
||||||
# existing fields, m2m fields, m2m related objects or related objects
|
# existing fields, m2m fields, m2m related objects or related objects
|
||||||
if f.rel:
|
if f.rel:
|
||||||
@ -1169,7 +1208,7 @@ def runfcgi(args):
|
|||||||
runfastcgi(args)
|
runfastcgi(args)
|
||||||
runfcgi.args = '[various KEY=val options, use `runfcgi help` for help]'
|
runfcgi.args = '[various KEY=val options, use `runfcgi help` for help]'
|
||||||
|
|
||||||
def test(verbosity, app_labels):
|
def test(app_labels, verbosity=1):
|
||||||
"Runs the test suite for the specified applications"
|
"Runs the test suite for the specified applications"
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db.models import get_app, get_apps
|
from django.db.models import get_app, get_apps
|
||||||
@ -1271,10 +1310,10 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None):
|
|||||||
help='Tells Django to NOT prompt the user for input of any kind.')
|
help='Tells Django to NOT prompt the user for input of any kind.')
|
||||||
parser.add_option('--noreload', action='store_false', dest='use_reloader', default=True,
|
parser.add_option('--noreload', action='store_false', dest='use_reloader', default=True,
|
||||||
help='Tells Django to NOT use the auto-reloader when running the development server.')
|
help='Tells Django to NOT use the auto-reloader when running the development server.')
|
||||||
parser.add_option('--verbosity', action='store', dest='verbosity', default='2',
|
parser.add_option('--verbosity', action='store', dest='verbosity', default='1',
|
||||||
type='choice', choices=['0', '1', '2'],
|
type='choice', choices=['0', '1', '2'],
|
||||||
help='Verbosity level; 0=minimal output, 1=normal output, 2=all output'),
|
help='Verbosity level; 0=minimal output, 1=normal output, 2=all output'),
|
||||||
parser.add_option('--adminmedia', dest='admin_media_path', default='', help='Lets you manually specify the directory to serve admin media from when running the development server.'),
|
parser.add_option('--adminmedia', dest='admin_media_path', default='', help='Specifies the directory from which to serve admin media for runserver.'),
|
||||||
|
|
||||||
options, args = parser.parse_args(argv[1:])
|
options, args = parser.parse_args(argv[1:])
|
||||||
|
|
||||||
@ -1320,7 +1359,7 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None):
|
|||||||
parser.print_usage_and_exit()
|
parser.print_usage_and_exit()
|
||||||
elif action == 'test':
|
elif action == 'test':
|
||||||
try:
|
try:
|
||||||
action_mapping[action](int(options.verbosity), args[1:])
|
action_mapping[action](args[1:], int(options.verbosity))
|
||||||
except IndexError:
|
except IndexError:
|
||||||
parser.print_usage_and_exit()
|
parser.print_usage_and_exit()
|
||||||
elif action in ('startapp', 'startproject'):
|
elif action in ('startapp', 'startproject'):
|
||||||
@ -1354,7 +1393,10 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None):
|
|||||||
if action not in NO_SQL_TRANSACTION:
|
if action not in NO_SQL_TRANSACTION:
|
||||||
print style.SQL_KEYWORD("BEGIN;")
|
print style.SQL_KEYWORD("BEGIN;")
|
||||||
for mod in mod_list:
|
for mod in mod_list:
|
||||||
output = action_mapping[action](mod)
|
if action == 'reset':
|
||||||
|
output = action_mapping[action](mod, options.interactive)
|
||||||
|
else:
|
||||||
|
output = action_mapping[action](mod)
|
||||||
if output:
|
if output:
|
||||||
print '\n'.join(output)
|
print '\n'.join(output)
|
||||||
if action not in NO_SQL_TRANSACTION:
|
if action not in NO_SQL_TRANSACTION:
|
||||||
|
@ -594,7 +594,7 @@ class AdminMediaHandler(object):
|
|||||||
Use this ONLY LOCALLY, for development! This hasn't been tested for
|
Use this ONLY LOCALLY, for development! This hasn't been tested for
|
||||||
security and is not super efficient.
|
security and is not super efficient.
|
||||||
"""
|
"""
|
||||||
def __init__(self, application, media_dir = None):
|
def __init__(self, application, media_dir=None):
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
self.application = application
|
self.application = application
|
||||||
if not media_dir:
|
if not media_dir:
|
||||||
|
@ -15,7 +15,8 @@ class Resolver404(Http404):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
class NoReverseMatch(Exception):
|
class NoReverseMatch(Exception):
|
||||||
pass
|
# Don't make this raise an error when used in a template.
|
||||||
|
silent_variable_failure = True
|
||||||
|
|
||||||
def get_mod_func(callback):
|
def get_mod_func(callback):
|
||||||
# Converts 'django.views.news.stories.story_detail' to
|
# Converts 'django.views.news.stories.story_detail' to
|
||||||
|
@ -249,7 +249,7 @@ def hasNoProfanities(field_data, all_data):
|
|||||||
Watch your mouth! The words "f--k" and "s--t" are not allowed here.
|
Watch your mouth! The words "f--k" and "s--t" are not allowed here.
|
||||||
"""
|
"""
|
||||||
field_data = field_data.lower() # normalize
|
field_data = field_data.lower() # normalize
|
||||||
words_seen = [w for w in settings.PROFANITIES_LIST if field_data.find(w) > -1]
|
words_seen = [w for w in settings.PROFANITIES_LIST if w in field_data]
|
||||||
if words_seen:
|
if words_seen:
|
||||||
from django.utils.text import get_text_list
|
from django.utils.text import get_text_list
|
||||||
plural = len(words_seen) > 1
|
plural = len(words_seen) > 1
|
||||||
@ -377,7 +377,7 @@ class IsValidFloat(object):
|
|||||||
if len(data) > max_allowed_length:
|
if len(data) > max_allowed_length:
|
||||||
raise ValidationError, ngettext("Please enter a valid decimal number with at most %s total digit.",
|
raise ValidationError, ngettext("Please enter a valid decimal number with at most %s total digit.",
|
||||||
"Please enter a valid decimal number with at most %s total digits.", self.max_digits) % self.max_digits
|
"Please enter a valid decimal number with at most %s total digits.", self.max_digits) % self.max_digits
|
||||||
if (not '.' in data and len(data) > (max_allowed_length - self.decimal_places)) or ('.' in data and len(data) > (self.max_digits - (self.decimal_places - len(data.split('.')[1])) + 1)):
|
if (not '.' in data and len(data) > (max_allowed_length - self.decimal_places - 1)) or ('.' in data and len(data) > (max_allowed_length - (self.decimal_places - len(data.split('.')[1])))):
|
||||||
raise ValidationError, ngettext( "Please enter a valid decimal number with a whole part of at most %s digit.",
|
raise ValidationError, ngettext( "Please enter a valid decimal number with a whole part of at most %s digit.",
|
||||||
"Please enter a valid decimal number with a whole part of at most %s digits.", str(self.max_digits-self.decimal_places)) % str(self.max_digits-self.decimal_places)
|
"Please enter a valid decimal number with a whole part of at most %s digits.", str(self.max_digits-self.decimal_places)) % str(self.max_digits-self.decimal_places)
|
||||||
if '.' in data and len(data.split('.')[1]) > self.decimal_places:
|
if '.' in data and len(data.split('.')[1]) > self.decimal_places:
|
||||||
|
@ -13,6 +13,7 @@ except ImportError, e:
|
|||||||
from MySQLdb.converters import conversions
|
from MySQLdb.converters import conversions
|
||||||
from MySQLdb.constants import FIELD_TYPE
|
from MySQLdb.constants import FIELD_TYPE
|
||||||
import types
|
import types
|
||||||
|
import re
|
||||||
|
|
||||||
DatabaseError = Database.DatabaseError
|
DatabaseError = Database.DatabaseError
|
||||||
|
|
||||||
@ -24,6 +25,12 @@ django_conversions.update({
|
|||||||
FIELD_TYPE.TIME: util.typecast_time,
|
FIELD_TYPE.TIME: util.typecast_time,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
# This should match the numerical portion of the version numbers (we can treat
|
||||||
|
# versions like 5.0.24 and 5.0.24a as the same). Based on the list of version
|
||||||
|
# at http://dev.mysql.com/doc/refman/4.1/en/news.html and
|
||||||
|
# http://dev.mysql.com/doc/refman/5.0/en/news.html .
|
||||||
|
server_version_re = re.compile(r'(\d{1,2})\.(\d{1,2})\.(\d{1,2})')
|
||||||
|
|
||||||
# This is an extra debug layer over MySQL queries, to display warnings.
|
# This is an extra debug layer over MySQL queries, to display warnings.
|
||||||
# It's only used when DEBUG=True.
|
# It's only used when DEBUG=True.
|
||||||
class MysqlDebugWrapper:
|
class MysqlDebugWrapper:
|
||||||
@ -61,6 +68,7 @@ class DatabaseWrapper(local):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.connection = None
|
self.connection = None
|
||||||
self.queries = []
|
self.queries = []
|
||||||
|
self.server_version = None
|
||||||
|
|
||||||
def _valid_connection(self):
|
def _valid_connection(self):
|
||||||
if self.connection is not None:
|
if self.connection is not None:
|
||||||
@ -110,6 +118,16 @@ class DatabaseWrapper(local):
|
|||||||
self.connection.close()
|
self.connection.close()
|
||||||
self.connection = None
|
self.connection = None
|
||||||
|
|
||||||
|
def get_server_version(self):
|
||||||
|
if not self.server_version:
|
||||||
|
if not self._valid_connection():
|
||||||
|
self.cursor()
|
||||||
|
m = server_version_re.match(self.connection.get_server_info())
|
||||||
|
if not m:
|
||||||
|
raise Exception('Unable to determine MySQL version from version string %r' % self.connection.get_server_info())
|
||||||
|
self.server_version = tuple([int(x) for x in m.groups()])
|
||||||
|
return self.server_version
|
||||||
|
|
||||||
supports_constraints = True
|
supports_constraints = True
|
||||||
|
|
||||||
def quote_name(name):
|
def quote_name(name):
|
||||||
|
@ -5,6 +5,7 @@ from django.core import validators
|
|||||||
from django import forms
|
from django import forms
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from django.utils.functional import curry
|
from django.utils.functional import curry
|
||||||
|
from django.utils.itercompat import tee
|
||||||
from django.utils.text import capfirst
|
from django.utils.text import capfirst
|
||||||
from django.utils.translation import gettext, gettext_lazy
|
from django.utils.translation import gettext, gettext_lazy
|
||||||
import datetime, os, time
|
import datetime, os, time
|
||||||
@ -80,7 +81,7 @@ class Field(object):
|
|||||||
self.prepopulate_from = prepopulate_from
|
self.prepopulate_from = prepopulate_from
|
||||||
self.unique_for_date, self.unique_for_month = unique_for_date, unique_for_month
|
self.unique_for_date, self.unique_for_month = unique_for_date, unique_for_month
|
||||||
self.unique_for_year = unique_for_year
|
self.unique_for_year = unique_for_year
|
||||||
self.choices = choices or []
|
self._choices = choices or []
|
||||||
self.radio_admin = radio_admin
|
self.radio_admin = radio_admin
|
||||||
self.help_text = help_text
|
self.help_text = help_text
|
||||||
self.db_column = db_column
|
self.db_column = db_column
|
||||||
@ -324,6 +325,14 @@ class Field(object):
|
|||||||
def bind(self, fieldmapping, original, bound_field_class):
|
def bind(self, fieldmapping, original, bound_field_class):
|
||||||
return bound_field_class(self, fieldmapping, original)
|
return bound_field_class(self, fieldmapping, original)
|
||||||
|
|
||||||
|
def _get_choices(self):
|
||||||
|
if hasattr(self._choices, 'next'):
|
||||||
|
choices, self._choices = tee(self._choices)
|
||||||
|
return choices
|
||||||
|
else:
|
||||||
|
return self._choices
|
||||||
|
choices = property(_get_choices)
|
||||||
|
|
||||||
class AutoField(Field):
|
class AutoField(Field):
|
||||||
empty_strings_allowed = False
|
empty_strings_allowed = False
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
@ -367,8 +376,8 @@ class BooleanField(Field):
|
|||||||
|
|
||||||
def to_python(self, value):
|
def to_python(self, value):
|
||||||
if value in (True, False): return value
|
if value in (True, False): return value
|
||||||
if value in ('t', 'True'): return True
|
if value in ('t', 'True', '1'): return True
|
||||||
if value in ('f', 'False'): return False
|
if value in ('f', 'False', '0'): return False
|
||||||
raise validators.ValidationError, gettext("This value must be either True or False.")
|
raise validators.ValidationError, gettext("This value must be either True or False.")
|
||||||
|
|
||||||
def get_manipulator_field_objs(self):
|
def get_manipulator_field_objs(self):
|
||||||
|
@ -618,7 +618,7 @@ class ManyToManyField(RelatedField, Field):
|
|||||||
msg = gettext_lazy('Separate multiple IDs with commas.')
|
msg = gettext_lazy('Separate multiple IDs with commas.')
|
||||||
else:
|
else:
|
||||||
msg = gettext_lazy('Hold down "Control", or "Command" on a Mac, to select more than one.')
|
msg = gettext_lazy('Hold down "Control", or "Command" on a Mac, to select more than one.')
|
||||||
self.help_text = string_concat(self.help_text, msg)
|
self.help_text = string_concat(self.help_text, ' ', msg)
|
||||||
|
|
||||||
def get_manipulator_field_objs(self):
|
def get_manipulator_field_objs(self):
|
||||||
if self.rel.raw_id_admin:
|
if self.rel.raw_id_admin:
|
||||||
|
@ -177,7 +177,7 @@ class AutomaticManipulator(forms.Manipulator):
|
|||||||
# case, because they'll be dealt with later.
|
# case, because they'll be dealt with later.
|
||||||
|
|
||||||
if f == related.field:
|
if f == related.field:
|
||||||
param = getattr(new_object, related.field.rel.field_name)
|
param = getattr(new_object, related.field.rel.get_related_field().attname)
|
||||||
elif (not self.change) and isinstance(f, AutoField):
|
elif (not self.change) and isinstance(f, AutoField):
|
||||||
param = None
|
param = None
|
||||||
elif self.change and (isinstance(f, FileField) or not child_follow.get(f.name, None)):
|
elif self.change and (isinstance(f, FileField) or not child_follow.get(f.name, None)):
|
||||||
@ -215,7 +215,10 @@ class AutomaticManipulator(forms.Manipulator):
|
|||||||
# Save many-to-many objects.
|
# Save many-to-many objects.
|
||||||
for f in related.opts.many_to_many:
|
for f in related.opts.many_to_many:
|
||||||
if child_follow.get(f.name, None) and not f.rel.edit_inline:
|
if child_follow.get(f.name, None) and not f.rel.edit_inline:
|
||||||
setattr(new_rel_obj, f.name, f.rel.to.objects.filter(pk__in=rel_new_data[f.attname]))
|
new_value = rel_new_data[f.attname]
|
||||||
|
if f.rel.raw_id_admin:
|
||||||
|
new_value = new_value[0]
|
||||||
|
setattr(new_rel_obj, f.name, f.rel.to.objects.filter(pk__in=new_value))
|
||||||
if self.change:
|
if self.change:
|
||||||
self.fields_changed.append('%s for %s "%s"' % (f.verbose_name, related.opts.verbose_name, new_rel_obj))
|
self.fields_changed.append('%s for %s "%s"' % (f.verbose_name, related.opts.verbose_name, new_rel_obj))
|
||||||
|
|
||||||
@ -300,7 +303,7 @@ def manipulator_validator_unique_together(field_name_list, opts, self, field_dat
|
|||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
raise validators.ValidationError, _("%(object)s with this %(type)s already exists for the given %(field)s.") % \
|
raise validators.ValidationError, _("%(object)s with this %(type)s already exists for the given %(field)s.") % \
|
||||||
{'object': capfirst(opts.verbose_name), 'type': field_list[0].verbose_name, 'field': get_text_list(field_name_list[1:], 'and')}
|
{'object': capfirst(opts.verbose_name), 'type': field_list[0].verbose_name, 'field': get_text_list([f.verbose_name for f in field_list[1:]], 'and')}
|
||||||
|
|
||||||
def manipulator_validator_unique_for_date(from_field, date_field, opts, lookup_type, self, field_data, all_data):
|
def manipulator_validator_unique_for_date(from_field, date_field, opts, lookup_type, self, field_data, all_data):
|
||||||
from django.db.models.fields.related import ManyToOneRel
|
from django.db.models.fields.related import ManyToOneRel
|
||||||
|
@ -707,30 +707,35 @@ def parse_lookup(kwarg_items, opts):
|
|||||||
joins, where, params = SortedDict(), [], []
|
joins, where, params = SortedDict(), [], []
|
||||||
|
|
||||||
for kwarg, value in kwarg_items:
|
for kwarg, value in kwarg_items:
|
||||||
if value is not None:
|
path = kwarg.split(LOOKUP_SEPARATOR)
|
||||||
path = kwarg.split(LOOKUP_SEPARATOR)
|
# Extract the last elements of the kwarg.
|
||||||
# Extract the last elements of the kwarg.
|
# The very-last is the lookup_type (equals, like, etc).
|
||||||
# The very-last is the lookup_type (equals, like, etc).
|
# The second-last is the table column on which the lookup_type is
|
||||||
# The second-last is the table column on which the lookup_type is
|
# to be performed. If this name is 'pk', it will be substituted with
|
||||||
# to be performed. If this name is 'pk', it will be substituted with
|
# the name of the primary key.
|
||||||
# the name of the primary key.
|
# If there is only one part, or the last part is not a query
|
||||||
# If there is only one part, or the last part is not a query
|
# term, assume that the query is an __exact
|
||||||
# term, assume that the query is an __exact
|
lookup_type = path.pop()
|
||||||
lookup_type = path.pop()
|
if lookup_type == 'pk':
|
||||||
if lookup_type == 'pk':
|
lookup_type = 'exact'
|
||||||
lookup_type = 'exact'
|
path.append(None)
|
||||||
path.append(None)
|
elif len(path) == 0 or lookup_type not in QUERY_TERMS:
|
||||||
elif len(path) == 0 or lookup_type not in QUERY_TERMS:
|
path.append(lookup_type)
|
||||||
path.append(lookup_type)
|
lookup_type = 'exact'
|
||||||
lookup_type = 'exact'
|
|
||||||
|
|
||||||
if len(path) < 1:
|
if len(path) < 1:
|
||||||
raise TypeError, "Cannot parse keyword query %r" % kwarg
|
raise TypeError, "Cannot parse keyword query %r" % kwarg
|
||||||
|
|
||||||
joins2, where2, params2 = lookup_inner(path, lookup_type, value, opts, opts.db_table, None)
|
if value is None:
|
||||||
joins.update(joins2)
|
# Interpret '__exact=None' as the sql '= NULL'; otherwise, reject
|
||||||
where.extend(where2)
|
# all uses of None as a query value.
|
||||||
params.extend(params2)
|
if lookup_type != 'exact':
|
||||||
|
raise ValueError, "Cannot use None as a query value"
|
||||||
|
|
||||||
|
joins2, where2, params2 = lookup_inner(path, lookup_type, value, opts, opts.db_table, None)
|
||||||
|
joins.update(joins2)
|
||||||
|
where.extend(where2)
|
||||||
|
params.extend(params2)
|
||||||
return joins, where, params
|
return joins, where, params
|
||||||
|
|
||||||
class FieldFound(Exception):
|
class FieldFound(Exception):
|
||||||
|
@ -54,6 +54,7 @@ class Manipulator(object):
|
|||||||
def get_validation_errors(self, new_data):
|
def get_validation_errors(self, new_data):
|
||||||
"Returns dictionary mapping field_names to error-message lists"
|
"Returns dictionary mapping field_names to error-message lists"
|
||||||
errors = {}
|
errors = {}
|
||||||
|
self.prepare(new_data)
|
||||||
for field in self.fields:
|
for field in self.fields:
|
||||||
errors.update(field.get_validation_errors(new_data))
|
errors.update(field.get_validation_errors(new_data))
|
||||||
val_name = 'validate_%s' % field.field_name
|
val_name = 'validate_%s' % field.field_name
|
||||||
@ -638,7 +639,7 @@ class CheckboxSelectMultipleField(SelectMultipleField):
|
|||||||
if str(value) in str_data_list:
|
if str(value) in str_data_list:
|
||||||
checked_html = ' checked="checked"'
|
checked_html = ' checked="checked"'
|
||||||
field_name = '%s%s' % (self.field_name, value)
|
field_name = '%s%s' % (self.field_name, value)
|
||||||
output.append('<li><input type="checkbox" id="%s" class="v%s" name="%s"%s /> <label for="%s">%s</label></li>' % \
|
output.append('<li><input type="checkbox" id="%s" class="v%s" name="%s"%s value="on" /> <label for="%s">%s</label></li>' % \
|
||||||
(self.get_id() + escape(value), self.__class__.__name__, field_name, checked_html,
|
(self.get_id() + escape(value), self.__class__.__name__, field_name, checked_html,
|
||||||
self.get_id() + escape(value), choice))
|
self.get_id() + escape(value), choice))
|
||||||
output.append('</ul>')
|
output.append('</ul>')
|
||||||
|
@ -2,6 +2,7 @@ from django.conf import settings
|
|||||||
from django import http
|
from django import http
|
||||||
from django.core.mail import mail_managers
|
from django.core.mail import mail_managers
|
||||||
import md5
|
import md5
|
||||||
|
import re
|
||||||
|
|
||||||
class CommonMiddleware(object):
|
class CommonMiddleware(object):
|
||||||
"""
|
"""
|
||||||
@ -61,12 +62,12 @@ class CommonMiddleware(object):
|
|||||||
# send a note to the managers.
|
# send a note to the managers.
|
||||||
domain = http.get_host(request)
|
domain = http.get_host(request)
|
||||||
referer = request.META.get('HTTP_REFERER', None)
|
referer = request.META.get('HTTP_REFERER', None)
|
||||||
is_internal = referer and (domain in referer)
|
is_internal = _is_internal_request(domain, referer)
|
||||||
path = request.get_full_path()
|
path = request.get_full_path()
|
||||||
if referer and not _is_ignorable_404(path) and (is_internal or '?' not in referer):
|
if referer and not _is_ignorable_404(path) and (is_internal or '?' not in referer):
|
||||||
ua = request.META.get('HTTP_USER_AGENT','<none>')
|
ua = request.META.get('HTTP_USER_AGENT', '<none>')
|
||||||
mail_managers("Broken %slink on %s" % ((is_internal and 'INTERNAL ' or ''), domain),
|
mail_managers("Broken %slink on %s" % ((is_internal and 'INTERNAL ' or ''), domain),
|
||||||
"Referrer: %s\nRequested URL: %s\nUser Agent: %s\n" % (referer, request.get_full_path(), ua))
|
"Referrer: %s\nRequested URL: %s\nUser agent: %s\n" % (referer, request.get_full_path(), ua))
|
||||||
return response
|
return response
|
||||||
|
|
||||||
# Use ETags, if requested.
|
# Use ETags, if requested.
|
||||||
@ -88,3 +89,8 @@ def _is_ignorable_404(uri):
|
|||||||
if uri.endswith(end):
|
if uri.endswith(end):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def _is_internal_request(domain, referer):
|
||||||
|
"Return true if the referring URL is the same domain as the current request"
|
||||||
|
# Different subdomains are treated as different domains.
|
||||||
|
return referer is not None and re.match("^https?://%s/" % re.escape(domain), referer)
|
||||||
|
@ -532,7 +532,7 @@ class FilterExpression(object):
|
|||||||
constant_arg, i18n_arg, var_arg = match.group("constant_arg", "i18n_arg", "var_arg")
|
constant_arg, i18n_arg, var_arg = match.group("constant_arg", "i18n_arg", "var_arg")
|
||||||
if i18n_arg:
|
if i18n_arg:
|
||||||
args.append((False, _(i18n_arg.replace(r'\"', '"'))))
|
args.append((False, _(i18n_arg.replace(r'\"', '"'))))
|
||||||
elif constant_arg:
|
elif constant_arg is not None:
|
||||||
args.append((False, constant_arg.replace(r'\"', '"')))
|
args.append((False, constant_arg.replace(r'\"', '"')))
|
||||||
elif var_arg:
|
elif var_arg:
|
||||||
args.append((True, var_arg))
|
args.append((True, var_arg))
|
||||||
|
@ -24,7 +24,7 @@ class ClientHandler(BaseHandler):
|
|||||||
dispatcher.send(signal=signals.request_started)
|
dispatcher.send(signal=signals.request_started)
|
||||||
try:
|
try:
|
||||||
request = WSGIRequest(environ)
|
request = WSGIRequest(environ)
|
||||||
response = self.get_response(request.path, request)
|
response = self.get_response(request)
|
||||||
|
|
||||||
# Apply response middleware
|
# Apply response middleware
|
||||||
for middleware_method in self._response_middleware:
|
for middleware_method in self._response_middleware:
|
||||||
|
31
django/utils/itercompat.py
Normal file
31
django/utils/itercompat.py
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
"""
|
||||||
|
Providing iterator functions that are not in all version of Python we support.
|
||||||
|
Where possible, we try to use the system-native version and only fall back to
|
||||||
|
these implementations if necessary.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import itertools
|
||||||
|
|
||||||
|
def compat_tee(iterable):
|
||||||
|
"""Return two independent iterators from a single iterable.
|
||||||
|
|
||||||
|
Based on http://www.python.org/doc/2.3.5/lib/itertools-example.html
|
||||||
|
"""
|
||||||
|
# Note: Using a dictionary and a list as the default arguments here is
|
||||||
|
# deliberate and safe in this instance.
|
||||||
|
def gen(next, data={}, cnt=[0]):
|
||||||
|
dpop = data.pop
|
||||||
|
for i in itertools.count():
|
||||||
|
if i == cnt[0]:
|
||||||
|
item = data[i] = next()
|
||||||
|
cnt[0] += 1
|
||||||
|
else:
|
||||||
|
item = dpop(i)
|
||||||
|
yield item
|
||||||
|
next = iter(iterable).next
|
||||||
|
return gen(next), gen(next)
|
||||||
|
|
||||||
|
if hasattr(itertools, 'tee'):
|
||||||
|
tee = itertools.tee
|
||||||
|
else:
|
||||||
|
tee = compat_tee
|
@ -102,7 +102,7 @@ def update_object(request, model, object_id=None, slug=None,
|
|||||||
except ObjectDoesNotExist:
|
except ObjectDoesNotExist:
|
||||||
raise Http404, "No %s found for %s" % (model._meta.verbose_name, lookup_kwargs)
|
raise Http404, "No %s found for %s" % (model._meta.verbose_name, lookup_kwargs)
|
||||||
|
|
||||||
manipulator = model.ChangeManipulator(getattr(object, object._meta.pk.name), follow=follow)
|
manipulator = model.ChangeManipulator(getattr(object, object._meta.pk.attname), follow=follow)
|
||||||
|
|
||||||
if request.POST:
|
if request.POST:
|
||||||
new_data = request.POST.copy()
|
new_data = request.POST.copy()
|
||||||
@ -142,7 +142,7 @@ def update_object(request, model, object_id=None, slug=None,
|
|||||||
else:
|
else:
|
||||||
c[key] = value
|
c[key] = value
|
||||||
response = HttpResponse(t.render(c))
|
response = HttpResponse(t.render(c))
|
||||||
populate_xheaders(request, response, model, getattr(object, object._meta.pk.name))
|
populate_xheaders(request, response, model, getattr(object, object._meta.pk.attname))
|
||||||
return response
|
return response
|
||||||
|
|
||||||
def delete_object(request, model, post_delete_redirect,
|
def delete_object(request, model, post_delete_redirect,
|
||||||
@ -196,5 +196,5 @@ def delete_object(request, model, post_delete_redirect,
|
|||||||
else:
|
else:
|
||||||
c[key] = value
|
c[key] = value
|
||||||
response = HttpResponse(t.render(c))
|
response = HttpResponse(t.render(c))
|
||||||
populate_xheaders(request, response, model, getattr(object, object._meta.pk.name))
|
populate_xheaders(request, response, model, getattr(object, object._meta.pk.attname))
|
||||||
return response
|
return response
|
||||||
|
@ -82,7 +82,7 @@ There are also a few styles for styling text.
|
|||||||
.help
|
.help
|
||||||
This is a custom class for blocks of inline help text explaining the
|
This is a custom class for blocks of inline help text explaining the
|
||||||
function of form elements. It makes text smaller and gray, and when applied
|
function of form elements. It makes text smaller and gray, and when applied
|
||||||
to ``p`` elements withing ``.form-row`` elements (see Form Styles below),
|
to ``p`` elements within ``.form-row`` elements (see Form Styles below),
|
||||||
it will offset the text to align with the form field. Use this for help
|
it will offset the text to align with the form field. Use this for help
|
||||||
text, instead of ``small quiet``. It works on other elements, but try to
|
text, instead of ``small quiet``. It works on other elements, but try to
|
||||||
put the class on a ``p`` whenever you can.
|
put the class on a ``p`` whenever you can.
|
||||||
|
@ -6,7 +6,7 @@ Since keeping multiple authentication databases in sync is a common problem when
|
|||||||
dealing with Apache, you can configuring Apache to authenticate against Django's
|
dealing with Apache, you can configuring Apache to authenticate against Django's
|
||||||
`authentication system`_ directly. For example, you could:
|
`authentication system`_ directly. For example, you could:
|
||||||
|
|
||||||
* Serve media files directly from Apache only to authenticated users.
|
* Serve static/media files directly from Apache only to authenticated users.
|
||||||
|
|
||||||
* Authenticate access to a Subversion_ repository against Django users with
|
* Authenticate access to a Subversion_ repository against Django users with
|
||||||
a certain permission.
|
a certain permission.
|
||||||
|
@ -82,7 +82,7 @@ that 90% of Django can be considered forwards-compatible at this point.
|
|||||||
That said, these APIs should *not* be considered stable, and are likely to
|
That said, these APIs should *not* be considered stable, and are likely to
|
||||||
change:
|
change:
|
||||||
|
|
||||||
- `Forms and validation`_ will most likely be compeltely rewritten to
|
- `Forms and validation`_ will most likely be completely rewritten to
|
||||||
deemphasize Manipulators in favor of validation-aware models.
|
deemphasize Manipulators in favor of validation-aware models.
|
||||||
|
|
||||||
- `Serialization`_ is under heavy development; changes are likely.
|
- `Serialization`_ is under heavy development; changes are likely.
|
||||||
@ -91,7 +91,7 @@ change:
|
|||||||
API changes may be necessary.
|
API changes may be necessary.
|
||||||
|
|
||||||
- Generic relations will most likely be moved out of core and into the
|
- Generic relations will most likely be moved out of core and into the
|
||||||
content-types contrib package to avoid core dependacies on optional
|
content-types contrib package to avoid core dependancies on optional
|
||||||
components.
|
components.
|
||||||
|
|
||||||
- The comments framework, which is yet undocumented, will likely get a complete
|
- The comments framework, which is yet undocumented, will likely get a complete
|
||||||
|
@ -66,8 +66,8 @@ Fields
|
|||||||
long and can contain any character. See the "Passwords" section below.
|
long and can contain any character. See the "Passwords" section below.
|
||||||
* ``is_staff`` -- Boolean. Designates whether this user can access the
|
* ``is_staff`` -- Boolean. Designates whether this user can access the
|
||||||
admin site.
|
admin site.
|
||||||
* ``is_active`` -- Boolean. Designates whether this user can log into the
|
* ``is_active`` -- Boolean. Designates whether this account can be used
|
||||||
Django admin. Set this to ``False`` instead of deleting accounts.
|
to log in. Set this flag to ``False`` instead of deleting accounts.
|
||||||
* ``is_superuser`` -- Boolean. Designates that this user has all permissions
|
* ``is_superuser`` -- Boolean. Designates that this user has all permissions
|
||||||
without explicitly assigning them.
|
without explicitly assigning them.
|
||||||
* ``last_login`` -- A datetime of the user's last login. Is set to the
|
* ``last_login`` -- A datetime of the user's last login. Is set to the
|
||||||
@ -99,7 +99,9 @@ custom methods:
|
|||||||
should prefer using ``is_authenticated()`` to this method.
|
should prefer using ``is_authenticated()`` to this method.
|
||||||
|
|
||||||
* ``is_authenticated()`` -- Always returns ``True``. This is a way to
|
* ``is_authenticated()`` -- Always returns ``True``. This is a way to
|
||||||
tell if the user has been authenticated.
|
tell if the user has been authenticated. This does not imply any
|
||||||
|
permissions, and doesn't check if the user is active - it only indicates
|
||||||
|
that the user has provided a valid username and password.
|
||||||
|
|
||||||
* ``get_full_name()`` -- Returns the ``first_name`` plus the ``last_name``,
|
* ``get_full_name()`` -- Returns the ``first_name`` plus the ``last_name``,
|
||||||
with a space in between.
|
with a space in between.
|
||||||
@ -120,13 +122,16 @@ custom methods:
|
|||||||
|
|
||||||
* ``has_perm(perm)`` -- Returns ``True`` if the user has the specified
|
* ``has_perm(perm)`` -- Returns ``True`` if the user has the specified
|
||||||
permission, where perm is in the format ``"package.codename"``.
|
permission, where perm is in the format ``"package.codename"``.
|
||||||
|
If the user is inactive, this method will always return ``False``.
|
||||||
|
|
||||||
* ``has_perms(perm_list)`` -- Returns ``True`` if the user has each of the
|
* ``has_perms(perm_list)`` -- Returns ``True`` if the user has each of the
|
||||||
specified permissions, where each perm is in the format
|
specified permissions, where each perm is in the format
|
||||||
``"package.codename"``.
|
``"package.codename"``. If the user is inactive, this method will
|
||||||
|
always return ``False``.
|
||||||
|
|
||||||
* ``has_module_perms(package_name)`` -- Returns ``True`` if the user has
|
* ``has_module_perms(package_name)`` -- Returns ``True`` if the user has
|
||||||
any permissions in the given package (the Django app label).
|
any permissions in the given package (the Django app label).
|
||||||
|
If the user is inactive, this method will always return ``False``.
|
||||||
|
|
||||||
* ``get_and_delete_messages()`` -- Returns a list of ``Message`` objects in
|
* ``get_and_delete_messages()`` -- Returns a list of ``Message`` objects in
|
||||||
the user's queue and deletes the messages from the queue.
|
the user's queue and deletes the messages from the queue.
|
||||||
@ -283,7 +288,10 @@ password is invalid, ``authenticate()`` returns ``None``. Example::
|
|||||||
from django.contrib.auth import authenticate
|
from django.contrib.auth import authenticate
|
||||||
user = authenticate(username='john', password='secret')
|
user = authenticate(username='john', password='secret')
|
||||||
if user is not None:
|
if user is not None:
|
||||||
print "You provided a correct username and password!"
|
if user.is_active:
|
||||||
|
print "You provided a correct username and password!"
|
||||||
|
else:
|
||||||
|
print "Your account has been disabled!"
|
||||||
else:
|
else:
|
||||||
print "Your username and password were incorrect."
|
print "Your username and password were incorrect."
|
||||||
|
|
||||||
@ -301,10 +309,13 @@ This example shows how you might use both ``authenticate()`` and ``login()``::
|
|||||||
password = request.POST['password']
|
password = request.POST['password']
|
||||||
user = authenticate(username=username, password=password)
|
user = authenticate(username=username, password=password)
|
||||||
if user is not None:
|
if user is not None:
|
||||||
login(request, user)
|
if user.is_active:
|
||||||
# Redirect to a success page.
|
login(request, user)
|
||||||
|
# Redirect to a success page.
|
||||||
|
else:
|
||||||
|
# Return a 'disabled account' error message
|
||||||
else:
|
else:
|
||||||
# Return an error message.
|
# Return an 'invalid login' error message.
|
||||||
|
|
||||||
How to log a user out
|
How to log a user out
|
||||||
---------------------
|
---------------------
|
||||||
@ -456,9 +467,9 @@ As a shortcut, you can use the convenient ``user_passes_test`` decorator::
|
|||||||
# ...
|
# ...
|
||||||
my_view = user_passes_test(lambda u: u.has_perm('polls.can_vote'))(my_view)
|
my_view = user_passes_test(lambda u: u.has_perm('polls.can_vote'))(my_view)
|
||||||
|
|
||||||
We are using this particular test as a relatively simple example, however be
|
We're using this particular test as a relatively simple example. However, if
|
||||||
aware that if you just want to test if a permission is available to a user,
|
you just want to test whether a permission is available to a user, you can use
|
||||||
you can use the ``permission_required()`` decorator described below.
|
the ``permission_required()`` decorator, described later in this document.
|
||||||
|
|
||||||
Here's the same thing, using Python 2.4's decorator syntax::
|
Here's the same thing, using Python 2.4's decorator syntax::
|
||||||
|
|
||||||
@ -495,20 +506,30 @@ Example in Python 2.4 syntax::
|
|||||||
The permission_required decorator
|
The permission_required decorator
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Since checking whether a user has a particular permission available to them is a
|
**New in Django development version**
|
||||||
relatively common operation, Django provides a shortcut for that particular
|
|
||||||
case: the ``permission_required()`` decorator. Using this decorator, the
|
It's a relatively common task to check whether a user has a particular
|
||||||
earlier example can be written as::
|
permission. For that reason, Django provides a shortcut for that case: the
|
||||||
|
``permission_required()`` decorator. Using this decorator, the earlier example
|
||||||
|
can be written as::
|
||||||
|
|
||||||
from django.contrib.auth.decorators import permission_required
|
from django.contrib.auth.decorators import permission_required
|
||||||
|
|
||||||
def my_view(request):
|
def my_view(request):
|
||||||
# ...
|
# ...
|
||||||
|
|
||||||
my_view = permission_required('polls.can_vote')(my_view)
|
my_view = permission_required('polls.can_vote')(my_view)
|
||||||
|
|
||||||
Note that ``permission_required()`` also takes an optional ``login_url``
|
Note that ``permission_required()`` also takes an optional ``login_url``
|
||||||
parameter.
|
parameter. Example::
|
||||||
|
|
||||||
|
from django.contrib.auth.decorators import permission_required
|
||||||
|
|
||||||
|
def my_view(request):
|
||||||
|
# ...
|
||||||
|
my_view = permission_required('polls.can_vote', login_url='/loginpage/')(my_view)
|
||||||
|
|
||||||
|
As in the ``login_required`` decorator, ``login_url`` defaults to
|
||||||
|
``'/accounts/login/'``.
|
||||||
|
|
||||||
Limiting access to generic views
|
Limiting access to generic views
|
||||||
--------------------------------
|
--------------------------------
|
||||||
|
@ -259,10 +259,10 @@ The tests cover:
|
|||||||
We appreciate any and all contributions to the test suite!
|
We appreciate any and all contributions to the test suite!
|
||||||
|
|
||||||
The Django tests all use the testing infrastructure that ships with Django for
|
The Django tests all use the testing infrastructure that ships with Django for
|
||||||
testing applications. See `Testing Django Applications`_ for an explanation of
|
testing applications. See `Testing Django applications`_ for an explanation of
|
||||||
how to write new tests.
|
how to write new tests.
|
||||||
|
|
||||||
.. _Testing Django Applications: http://www.djangoproject.com/documentation/testing/
|
.. _Testing Django applications: http://www.djangoproject.com/documentation/testing/
|
||||||
|
|
||||||
Running the unit tests
|
Running the unit tests
|
||||||
----------------------
|
----------------------
|
||||||
@ -273,7 +273,7 @@ To run the tests, ``cd`` to the ``tests/`` directory and type::
|
|||||||
|
|
||||||
Yes, the unit tests need a settings module, but only for database connection
|
Yes, the unit tests need a settings module, but only for database connection
|
||||||
info -- the ``DATABASE_ENGINE``, ``DATABASE_USER`` and ``DATABASE_PASSWORD``.
|
info -- the ``DATABASE_ENGINE``, ``DATABASE_USER`` and ``DATABASE_PASSWORD``.
|
||||||
You will also need a ``ROOT_URLCONF`` setting (it's value is ignored; it just
|
You will also need a ``ROOT_URLCONF`` setting (its value is ignored; it just
|
||||||
needs to be present) and a ``SITE_ID`` setting (any integer value will do) in
|
needs to be present) and a ``SITE_ID`` setting (any integer value will do) in
|
||||||
order for all the tests to pass.
|
order for all the tests to pass.
|
||||||
|
|
||||||
|
@ -876,15 +876,18 @@ The database API supports the following lookup types:
|
|||||||
exact
|
exact
|
||||||
~~~~~
|
~~~~~
|
||||||
|
|
||||||
Exact match.
|
Exact match. If the value provided for comparison is ``None``, it will
|
||||||
|
be interpreted as an SQL ``NULL`` (See isnull_ for more details).
|
||||||
|
|
||||||
Example::
|
Examples::
|
||||||
|
|
||||||
Entry.objects.get(id__exact=14)
|
Entry.objects.get(id__exact=14)
|
||||||
|
Entry.objects.get(id__exact=None)
|
||||||
|
|
||||||
SQL equivalent::
|
SQL equivalents::
|
||||||
|
|
||||||
SELECT ... WHERE id = 14;
|
SELECT ... WHERE id = 14;
|
||||||
|
SELECT ... WHERE id = NULL;
|
||||||
|
|
||||||
iexact
|
iexact
|
||||||
~~~~~~
|
~~~~~~
|
||||||
@ -1103,8 +1106,8 @@ such as January 3, July 3, etc.
|
|||||||
isnull
|
isnull
|
||||||
~~~~~~
|
~~~~~~
|
||||||
|
|
||||||
``NULL`` or ``IS NOT NULL`` match. Takes either ``True`` or ``False``, which
|
Takes either ``True`` or ``False``, which correspond to SQL queries of
|
||||||
correspond to ``IS NULL`` and ``IS NOT NULL``, respectively.
|
``IS NULL`` and ``IS NOT NULL``, respectively.
|
||||||
|
|
||||||
Example::
|
Example::
|
||||||
|
|
||||||
@ -1114,6 +1117,14 @@ SQL equivalent::
|
|||||||
|
|
||||||
SELECT ... WHERE pub_date IS NULL;
|
SELECT ... WHERE pub_date IS NULL;
|
||||||
|
|
||||||
|
.. admonition:: ``__isnull=True`` vs ``__exact=None``
|
||||||
|
|
||||||
|
There is an important difference between ``__isnull=True`` and
|
||||||
|
``__exact=None``. ``__exact=None`` will *always* return an empty result
|
||||||
|
set, because SQL requires that no value is equal to ``NULL``.
|
||||||
|
``__isnull`` determines if the field is currently holding the value
|
||||||
|
of ``NULL`` without performing a comparison.
|
||||||
|
|
||||||
search
|
search
|
||||||
~~~~~~
|
~~~~~~
|
||||||
|
|
||||||
|
@ -392,10 +392,10 @@ and `2` is verbose output.
|
|||||||
Example usage::
|
Example usage::
|
||||||
django-admin.py manage.py --adminmedia=/tmp/new-admin-style/
|
django-admin.py manage.py --adminmedia=/tmp/new-admin-style/
|
||||||
|
|
||||||
Tell Django where to find the various stylesheets and Javascript files for the
|
Tells Django where to find the various CSS and JavaScript files for the admin
|
||||||
admin interface when running the development server. Normally these files are
|
interface when running the development server. Normally these files are served
|
||||||
served out of the Django source tree, but since some designers change these
|
out of the Django source tree, but because some designers customize these files
|
||||||
files for their site, this option allows you to test against custom versions.
|
for their site, this option allows you to test against custom versions.
|
||||||
|
|
||||||
Extra niceties
|
Extra niceties
|
||||||
==============
|
==============
|
||||||
|
18
docs/faq.txt
18
docs/faq.txt
@ -227,9 +227,7 @@ When will you release Django 1.0?
|
|||||||
|
|
||||||
Short answer: When we're comfortable with Django's APIs, have added all
|
Short answer: When we're comfortable with Django's APIs, have added all
|
||||||
features that we feel are necessary to earn a "1.0" status, and are ready to
|
features that we feel are necessary to earn a "1.0" status, and are ready to
|
||||||
begin maintaining backwards compatibility. This should happen in a couple of
|
begin maintaining backwards compatibility.
|
||||||
months or so, although it's entirely possible that it could happen earlier.
|
|
||||||
That translates into summer 2006.
|
|
||||||
|
|
||||||
The merging of Django's `magic-removal branch`_ went a long way toward Django
|
The merging of Django's `magic-removal branch`_ went a long way toward Django
|
||||||
1.0.
|
1.0.
|
||||||
@ -313,6 +311,18 @@ PostgreSQL fans, and MySQL_ and `SQLite 3`_ are also supported.
|
|||||||
.. _MySQL: http://www.mysql.com/
|
.. _MySQL: http://www.mysql.com/
|
||||||
.. _`SQLite 3`: http://www.sqlite.org/
|
.. _`SQLite 3`: http://www.sqlite.org/
|
||||||
|
|
||||||
|
Do I lose anything by using Python 2.3 versus newer Python versions, such as Python 2.5?
|
||||||
|
----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
No. Django itself is guaranteed to work with any version of Python from 2.3
|
||||||
|
and higher.
|
||||||
|
|
||||||
|
If you use a Python version newer than 2.3, you will, of course, be able to
|
||||||
|
take advantage of newer Python features in your own code, along with the speed
|
||||||
|
improvements and other optimizations that have been made to the Python language
|
||||||
|
itself. But the Django framework itself should work equally well on 2.3 as it
|
||||||
|
does on 2.4 or 2.5.
|
||||||
|
|
||||||
Do I have to use mod_python?
|
Do I have to use mod_python?
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
@ -487,7 +497,7 @@ specify an object to edit or delete.
|
|||||||
How do I add database-specific options to my CREATE TABLE statements, such as specifying MyISAM as the table type?
|
How do I add database-specific options to my CREATE TABLE statements, such as specifying MyISAM as the table type?
|
||||||
------------------------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
We try to avoid adding special cases in the Django code to accomodate all the
|
We try to avoid adding special cases in the Django code to accommodate all the
|
||||||
database-specific options such as table type, etc. If you'd like to use any of
|
database-specific options such as table type, etc. If you'd like to use any of
|
||||||
these options, create an `SQL initial data file`_ that contains ``ALTER TABLE``
|
these options, create an `SQL initial data file`_ that contains ``ALTER TABLE``
|
||||||
statements that do what you want to do. The initial data files are executed in
|
statements that do what you want to do. The initial data files are executed in
|
||||||
|
@ -211,7 +211,7 @@ Below is the finished view::
|
|||||||
def create_place(request):
|
def create_place(request):
|
||||||
manipulator = Place.AddManipulator()
|
manipulator = Place.AddManipulator()
|
||||||
|
|
||||||
if request.POST:
|
if request.method == 'POST':
|
||||||
# If data was POSTed, we're trying to create a new Place.
|
# If data was POSTed, we're trying to create a new Place.
|
||||||
new_data = request.POST.copy()
|
new_data = request.POST.copy()
|
||||||
|
|
||||||
@ -309,7 +309,7 @@ about editing an existing one? It's shockingly similar to creating a new one::
|
|||||||
# Grab the Place object in question for future use.
|
# Grab the Place object in question for future use.
|
||||||
place = manipulator.original_object
|
place = manipulator.original_object
|
||||||
|
|
||||||
if request.POST:
|
if request.method == 'POST':
|
||||||
new_data = request.POST.copy()
|
new_data = request.POST.copy()
|
||||||
errors = manipulator.get_validation_errors(new_data)
|
errors = manipulator.get_validation_errors(new_data)
|
||||||
if not errors:
|
if not errors:
|
||||||
@ -391,7 +391,7 @@ Here's a simple function that might drive the above form::
|
|||||||
|
|
||||||
def contact_form(request):
|
def contact_form(request):
|
||||||
manipulator = ContactManipulator()
|
manipulator = ContactManipulator()
|
||||||
if request.POST:
|
if request.method == 'POST':
|
||||||
new_data = request.POST.copy()
|
new_data = request.POST.copy()
|
||||||
errors = manipulator.get_validation_errors(new_data)
|
errors = manipulator.get_validation_errors(new_data)
|
||||||
if not errors:
|
if not errors:
|
||||||
@ -481,15 +481,15 @@ the data being validated.
|
|||||||
Also, because consistency in user interfaces is important, we strongly urge you
|
Also, because consistency in user interfaces is important, we strongly urge you
|
||||||
to put punctuation at the end of your validation messages.
|
to put punctuation at the end of your validation messages.
|
||||||
|
|
||||||
When Are Validators Called?
|
When are validators called?
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
After a form has been submitted, Django first checks to see that all the
|
After a form has been submitted, Django first checks to see that all the
|
||||||
required fields are present and non-empty. For each field that passes that
|
required fields are present and non-empty. For each field that passes that
|
||||||
test *and if the form submission contained data* for that field, all the
|
test *and if the form submission contained data* for that field, all the
|
||||||
validators for that field are called in turn. The emphasised portion in the
|
validators for that field are called in turn. The emphasized portion in the
|
||||||
last sentence is important: if a form field is not submitted (because it
|
last sentence is important: if a form field is not submitted (because it
|
||||||
contains no data -- which is normal HTML behaviour), the validators are not
|
contains no data -- which is normal HTML behavior), the validators are not
|
||||||
run against the field.
|
run against the field.
|
||||||
|
|
||||||
This feature is particularly important for models using
|
This feature is particularly important for models using
|
||||||
@ -497,18 +497,17 @@ This feature is particularly important for models using
|
|||||||
``forms.CheckBoxField``. If the checkbox is not selected, it will not
|
``forms.CheckBoxField``. If the checkbox is not selected, it will not
|
||||||
contribute to the form submission.
|
contribute to the form submission.
|
||||||
|
|
||||||
If you would like your validator to *always* run, regardless of whether the
|
If you would like your validator to run *always*, regardless of whether its
|
||||||
field it is attached to contains any data, set the ``always_test`` attribute
|
attached field contains any data, set the ``always_test`` attribute on the
|
||||||
on the validator function. For example::
|
validator function. For example::
|
||||||
|
|
||||||
def my_custom_validator(field_data, all_data):
|
def my_custom_validator(field_data, all_data):
|
||||||
# ...
|
# ...
|
||||||
|
|
||||||
my_custom_validator.always_test = True
|
my_custom_validator.always_test = True
|
||||||
|
|
||||||
This validator will always be executed for any field it is attached to.
|
This validator will always be executed for any field it is attached to.
|
||||||
|
|
||||||
Ready-made Validators
|
Ready-made validators
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
Writing your own validator is not difficult, but there are some situations
|
Writing your own validator is not difficult, but there are some situations
|
||||||
@ -580,7 +579,7 @@ fails. If no message is passed in, a default message is used.
|
|||||||
``ValidateIfOtherFieldEquals``
|
``ValidateIfOtherFieldEquals``
|
||||||
Takes three parameters: ``other_field``, ``other_value`` and
|
Takes three parameters: ``other_field``, ``other_value`` and
|
||||||
``validator_list``, in that order. If ``other_field`` has a value of
|
``validator_list``, in that order. If ``other_field`` has a value of
|
||||||
``other_vaue``, then the validators in ``validator_list`` are all run
|
``other_value``, then the validators in ``validator_list`` are all run
|
||||||
against the current field.
|
against the current field.
|
||||||
|
|
||||||
``RequiredIfOtherFieldNotGiven``
|
``RequiredIfOtherFieldNotGiven``
|
||||||
|
@ -184,7 +184,7 @@ a date in the *future* are not included unless you set ``allow_future`` to
|
|||||||
the view's template. See the `RequestContext docs`_.
|
the view's template. See the `RequestContext docs`_.
|
||||||
|
|
||||||
* ``mimetype``: The MIME type to use for the resulting document. Defaults
|
* ``mimetype``: The MIME type to use for the resulting document. Defaults
|
||||||
to the value of the ``DEFAULT_MIME_TYPE`` setting.
|
to the value of the ``DEFAULT_CONTENT_TYPE`` setting.
|
||||||
|
|
||||||
* ``allow_future``: A boolean specifying whether to include "future"
|
* ``allow_future``: A boolean specifying whether to include "future"
|
||||||
objects on this page, where "future" means objects in which the field
|
objects on this page, where "future" means objects in which the field
|
||||||
@ -270,7 +270,7 @@ to ``True``.
|
|||||||
this is ``False``.
|
this is ``False``.
|
||||||
|
|
||||||
* ``mimetype``: The MIME type to use for the resulting document. Defaults
|
* ``mimetype``: The MIME type to use for the resulting document. Defaults
|
||||||
to the value of the ``DEFAULT_MIME_TYPE`` setting.
|
to the value of the ``DEFAULT_CONTENT_TYPE`` setting.
|
||||||
|
|
||||||
* ``allow_future``: A boolean specifying whether to include "future"
|
* ``allow_future``: A boolean specifying whether to include "future"
|
||||||
objects on this page, where "future" means objects in which the field
|
objects on this page, where "future" means objects in which the field
|
||||||
@ -357,7 +357,7 @@ date in the *future* are not displayed unless you set ``allow_future`` to
|
|||||||
determining the variable's name.
|
determining the variable's name.
|
||||||
|
|
||||||
* ``mimetype``: The MIME type to use for the resulting document. Defaults
|
* ``mimetype``: The MIME type to use for the resulting document. Defaults
|
||||||
to the value of the ``DEFAULT_MIME_TYPE`` setting.
|
to the value of the ``DEFAULT_CONTENT_TYPE`` setting.
|
||||||
|
|
||||||
* ``allow_future``: A boolean specifying whether to include "future"
|
* ``allow_future``: A boolean specifying whether to include "future"
|
||||||
objects on this page, where "future" means objects in which the field
|
objects on this page, where "future" means objects in which the field
|
||||||
@ -438,7 +438,7 @@ in the *future* are not displayed unless you set ``allow_future`` to ``True``.
|
|||||||
determining the variable's name.
|
determining the variable's name.
|
||||||
|
|
||||||
* ``mimetype``: The MIME type to use for the resulting document. Defaults
|
* ``mimetype``: The MIME type to use for the resulting document. Defaults
|
||||||
to the value of the ``DEFAULT_MIME_TYPE`` setting.
|
to the value of the ``DEFAULT_CONTENT_TYPE`` setting.
|
||||||
|
|
||||||
* ``allow_future``: A boolean specifying whether to include "future"
|
* ``allow_future``: A boolean specifying whether to include "future"
|
||||||
objects on this page, where "future" means objects in which the field
|
objects on this page, where "future" means objects in which the field
|
||||||
@ -523,7 +523,7 @@ you set ``allow_future`` to ``True``.
|
|||||||
determining the variable's name.
|
determining the variable's name.
|
||||||
|
|
||||||
* ``mimetype``: The MIME type to use for the resulting document. Defaults
|
* ``mimetype``: The MIME type to use for the resulting document. Defaults
|
||||||
to the value of the ``DEFAULT_MIME_TYPE`` setting.
|
to the value of the ``DEFAULT_CONTENT_TYPE`` setting.
|
||||||
|
|
||||||
* ``allow_future``: A boolean specifying whether to include "future"
|
* ``allow_future``: A boolean specifying whether to include "future"
|
||||||
objects on this page, where "future" means objects in which the field
|
objects on this page, where "future" means objects in which the field
|
||||||
@ -633,7 +633,7 @@ future, the view will throw a 404 error by default, unless you set
|
|||||||
to use in the template context. By default, this is ``'object'``.
|
to use in the template context. By default, this is ``'object'``.
|
||||||
|
|
||||||
* ``mimetype``: The MIME type to use for the resulting document. Defaults
|
* ``mimetype``: The MIME type to use for the resulting document. Defaults
|
||||||
to the value of the ``DEFAULT_MIME_TYPE`` setting.
|
to the value of the ``DEFAULT_CONTENT_TYPE`` setting.
|
||||||
|
|
||||||
* ``allow_future``: A boolean specifying whether to include "future"
|
* ``allow_future``: A boolean specifying whether to include "future"
|
||||||
objects on this page, where "future" means objects in which the field
|
objects on this page, where "future" means objects in which the field
|
||||||
@ -707,7 +707,7 @@ A page representing a list of objects.
|
|||||||
determining the variable's name.
|
determining the variable's name.
|
||||||
|
|
||||||
* ``mimetype``: The MIME type to use for the resulting document. Defaults
|
* ``mimetype``: The MIME type to use for the resulting document. Defaults
|
||||||
to the value of the ``DEFAULT_MIME_TYPE`` setting.
|
to the value of the ``DEFAULT_CONTENT_TYPE`` setting.
|
||||||
|
|
||||||
**Template name:**
|
**Template name:**
|
||||||
|
|
||||||
@ -819,7 +819,7 @@ A page representing an individual object.
|
|||||||
to use in the template context. By default, this is ``'object'``.
|
to use in the template context. By default, this is ``'object'``.
|
||||||
|
|
||||||
* ``mimetype``: The MIME type to use for the resulting document. Defaults
|
* ``mimetype``: The MIME type to use for the resulting document. Defaults
|
||||||
to the value of the ``DEFAULT_MIME_TYPE`` setting.
|
to the value of the ``DEFAULT_CONTENT_TYPE`` setting.
|
||||||
|
|
||||||
**Template name:**
|
**Template name:**
|
||||||
|
|
||||||
|
@ -84,9 +84,12 @@ Installing the official version
|
|||||||
|
|
||||||
Note that the last command will automatically download and install setuptools_
|
Note that the last command will automatically download and install setuptools_
|
||||||
if you don't already have it installed. This requires a working Internet
|
if you don't already have it installed. This requires a working Internet
|
||||||
|
connection and may cause problems on Python 2.5. If you run into problems,
|
||||||
|
try using our development version by following the instructions below. The
|
||||||
|
development version no longer uses setuptools nor requires an Internet
|
||||||
connection.
|
connection.
|
||||||
|
|
||||||
This will install Django in your Python installation's ``site-packages``
|
The command will install Django in your Python installation's ``site-packages``
|
||||||
directory.
|
directory.
|
||||||
|
|
||||||
.. _setuptools: http://peak.telecommunity.com/DevCenter/setuptools
|
.. _setuptools: http://peak.telecommunity.com/DevCenter/setuptools
|
||||||
@ -94,19 +97,34 @@ directory.
|
|||||||
Installing the development version
|
Installing the development version
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
1. Make sure you have Subversion_ installed.
|
If you'd like to be able to update your Django code occasionally with the
|
||||||
2. ``svn co http://code.djangoproject.com/svn/django/trunk/ django_src``
|
latest bug fixes and improvements, follow these instructions:
|
||||||
3. Symlink ``django_src/django`` so that ``django`` is within your Python
|
|
||||||
``site-packages`` directory:
|
|
||||||
|
|
||||||
``ln -s `pwd`/django_src/django /usr/lib/python2.3/site-packages/django``
|
1. Make sure you have Subversion_ installed.
|
||||||
|
2. Check out the Django code into your Python ``site-packages`` directory.
|
||||||
|
On Linux / Mac OSX / Unix, do this::
|
||||||
|
|
||||||
|
svn co http://code.djangoproject.com/svn/django/trunk/ django_src
|
||||||
|
ln -s `pwd`/django_src/django /usr/lib/python2.3/site-packages/django
|
||||||
|
|
||||||
(In the above line, change ``python2.3`` to match your current Python version.)
|
(In the above line, change ``python2.3`` to match your current Python version.)
|
||||||
|
|
||||||
You don't have to run ``python setup.py install``.
|
On Windows, do this::
|
||||||
|
|
||||||
When you want to update your code, just run the command ``svn update`` from
|
svn co http://code.djangoproject.com/svn/django/trunk/django c:\Python24\lib\site-packages\django
|
||||||
within the ``django_src`` directory.
|
|
||||||
|
4. Copy the file ``django_src/django/bin/django-admin.py`` to somewhere on your
|
||||||
|
system path, such as ``/usr/local/bin`` (Unix) or ``C:\Python24\Scripts``
|
||||||
|
(Windows). This step simply lets you type ``django-admin.py`` from within
|
||||||
|
any directory, rather than having to qualify the command with the full path
|
||||||
|
to the file.
|
||||||
|
|
||||||
|
You *don't* have to run ``python setup.py install``, because that command
|
||||||
|
takes care of steps 3 and 4 for you.
|
||||||
|
|
||||||
|
When you want to update your copy of the Django source code, just run the
|
||||||
|
command ``svn update`` from within the ``django`` directory. When you do this,
|
||||||
|
Subversion will automatically download any changes.
|
||||||
|
|
||||||
.. _`download page`: http://www.djangoproject.com/download/
|
.. _`download page`: http://www.djangoproject.com/download/
|
||||||
.. _Subversion: http://subversion.tigris.org/
|
.. _Subversion: http://subversion.tigris.org/
|
||||||
|
@ -188,7 +188,8 @@ JavaScript shortcuts.
|
|||||||
~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~
|
||||||
|
|
||||||
A ``CharField`` that checks that the value is a valid e-mail address.
|
A ``CharField`` that checks that the value is a valid e-mail address.
|
||||||
This doesn't accept ``maxlength``.
|
This doesn't accept ``maxlength``; its ``maxlength`` is automatically set to
|
||||||
|
75.
|
||||||
|
|
||||||
``FileField``
|
``FileField``
|
||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
@ -545,7 +546,7 @@ The default value for the field.
|
|||||||
|
|
||||||
If ``False``, the field will not be editable in the admin or via form
|
If ``False``, the field will not be editable in the admin or via form
|
||||||
processing using the object's ``AddManipulator`` or ``ChangeManipulator``
|
processing using the object's ``AddManipulator`` or ``ChangeManipulator``
|
||||||
classes. Default is ``True``.
|
classes. Default is ``True``.
|
||||||
|
|
||||||
``help_text``
|
``help_text``
|
||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
|
@ -110,7 +110,7 @@ many common questions appear with some regularity, and any particular problem
|
|||||||
may already have been answered.
|
may already have been answered.
|
||||||
|
|
||||||
Finally, for those who prefer the more immediate feedback offered by IRC,
|
Finally, for those who prefer the more immediate feedback offered by IRC,
|
||||||
there's a #django channel or irc.freenode.net that is regularly populated by
|
there's a #django channel on irc.freenode.net that is regularly populated by
|
||||||
Django users and developers from around the world. Friendly people are usually
|
Django users and developers from around the world. Friendly people are usually
|
||||||
available at any hour of the day -- to help, or just to chat.
|
available at any hour of the day -- to help, or just to chat.
|
||||||
|
|
||||||
|
@ -341,9 +341,9 @@ hard-coded strings. If you use this technique, follow these guidelines:
|
|||||||
Methods
|
Methods
|
||||||
-------
|
-------
|
||||||
|
|
||||||
``__init__(content='', mimetype=DEFAULT_MIME_TYPE)``
|
``__init__(content='', mimetype=DEFAULT_CONTENT_TYPE)``
|
||||||
Instantiates an ``HttpResponse`` object with the given page content (a
|
Instantiates an ``HttpResponse`` object with the given page content (a
|
||||||
string) and MIME type. The ``DEFAULT_MIME_TYPE`` is ``'text/html'``.
|
string) and MIME type. The ``DEFAULT_CONTENT_TYPE`` is ``'text/html'``.
|
||||||
|
|
||||||
``content`` can be an iterator or a string. If it's an iterator, it should
|
``content`` can be an iterator or a string. If it's an iterator, it should
|
||||||
return strings, and those strings will be joined together to form the
|
return strings, and those strings will be joined together to form the
|
||||||
|
@ -96,15 +96,15 @@ Django "ships" with a few included serializers:
|
|||||||
.. _json: http://json.org/
|
.. _json: http://json.org/
|
||||||
.. _simplejson: http://undefined.org/python/#simplejson
|
.. _simplejson: http://undefined.org/python/#simplejson
|
||||||
|
|
||||||
Notes For Specific Serialization Formats
|
Notes for specific serialization formats
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
|
|
||||||
json
|
json
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
If you are using UTF-8 (or any other non-ASCII encoding) data with the JSON
|
If you're using UTF-8 (or any other non-ASCII encoding) data with the JSON
|
||||||
serializer, you must pass ``ensure_ascii=False`` as a parameter to the
|
serializer, you must pass ``ensure_ascii=False`` as a parameter to the
|
||||||
``serialize()`` call. Otherwise the output will not be encoded correctly.
|
``serialize()`` call. Otherwise, the output won't be encoded correctly.
|
||||||
|
|
||||||
For example::
|
For example::
|
||||||
|
|
||||||
|
@ -401,15 +401,6 @@ Subject-line prefix for e-mail messages sent with ``django.core.mail.mail_admins
|
|||||||
or ``django.core.mail.mail_managers``. You'll probably want to include the
|
or ``django.core.mail.mail_managers``. You'll probably want to include the
|
||||||
trailing space.
|
trailing space.
|
||||||
|
|
||||||
ENABLE_PSYCO
|
|
||||||
------------
|
|
||||||
|
|
||||||
Default: ``False``
|
|
||||||
|
|
||||||
Whether to enable Psyco, which optimizes Python code. Requires Psyco_.
|
|
||||||
|
|
||||||
.. _Psyco: http://psyco.sourceforge.net/
|
|
||||||
|
|
||||||
IGNORABLE_404_ENDS
|
IGNORABLE_404_ENDS
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
@ -599,8 +590,11 @@ See also ``APPEND_SLASH``.
|
|||||||
PROFANITIES_LIST
|
PROFANITIES_LIST
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
A list of profanities that will trigger a validation error when the
|
A tuple of profanities, as strings, that will trigger a validation error when
|
||||||
``hasNoProfanities`` validator is called.
|
the ``hasNoProfanities`` validator is called.
|
||||||
|
|
||||||
|
We don't list the default values here, because that would be profane. To see
|
||||||
|
the default values, see the file ``django/conf/global_settings.py``.
|
||||||
|
|
||||||
ROOT_URLCONF
|
ROOT_URLCONF
|
||||||
------------
|
------------
|
||||||
|
@ -540,6 +540,11 @@ The arguments can be hard-coded strings, so the following is valid::
|
|||||||
...
|
...
|
||||||
{% endifequal %}
|
{% endifequal %}
|
||||||
|
|
||||||
|
It is only possible to compare an argument to template variables or strings.
|
||||||
|
You cannot check for equality with Python objects such as ``True`` or
|
||||||
|
``False``. If you need to test if something is true or false, use the ``if``
|
||||||
|
and ``ifnot`` tags instead.
|
||||||
|
|
||||||
ifnotequal
|
ifnotequal
|
||||||
~~~~~~~~~~
|
~~~~~~~~~~
|
||||||
|
|
||||||
@ -1051,7 +1056,7 @@ Formats a date as the time since that date (i.e. "4 days, 6 hours").
|
|||||||
Takes an optional argument that is a variable containing the date to use as
|
Takes an optional argument that is a variable containing the date to use as
|
||||||
the comparison point (without the argument, the comparison point is *now*).
|
the comparison point (without the argument, the comparison point is *now*).
|
||||||
For example, if ``blog_date`` is a date instance representing midnight on 1
|
For example, if ``blog_date`` is a date instance representing midnight on 1
|
||||||
June 2006, and ``comment_date`` is a date instanace for 08:00 on 1 June 2006,
|
June 2006, and ``comment_date`` is a date instance for 08:00 on 1 June 2006,
|
||||||
then ``{{ comment_date|timesince:blog_date }}`` would return "8 hours".
|
then ``{{ comment_date|timesince:blog_date }}`` would return "8 hours".
|
||||||
|
|
||||||
timeuntil
|
timeuntil
|
||||||
|
@ -212,6 +212,21 @@ template tags. If an invalid variable is provided to one of these template
|
|||||||
tags, the variable will be interpreted as ``None``. Filters are always
|
tags, the variable will be interpreted as ``None``. Filters are always
|
||||||
applied to invalid variables within these template tags.
|
applied to invalid variables within these template tags.
|
||||||
|
|
||||||
|
.. admonition:: For debug purposes only!
|
||||||
|
|
||||||
|
While ``TEMPLATE_STRING_IF_INVALID`` can be a useful debugging tool,
|
||||||
|
it is a bad idea to turn it on as a 'development default'.
|
||||||
|
|
||||||
|
Many templates, including those in the Admin site, rely upon the
|
||||||
|
silence of the template system when a non-existent variable is
|
||||||
|
encountered. If you assign a value other than ``''`` to
|
||||||
|
``TEMPLATE_STRING_IF_INVALID``, you will experience rendering
|
||||||
|
problems with these templates and sites.
|
||||||
|
|
||||||
|
Generally, ``TEMPLATE_STRING_IF_INVALID`` should only be enabled
|
||||||
|
in order to debug a specific template problem, then cleared
|
||||||
|
once debugging is complete.
|
||||||
|
|
||||||
Playing with Context objects
|
Playing with Context objects
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
@ -296,6 +311,20 @@ optional, third positional argument, ``processors``. In this example, the
|
|||||||
'foo': 'bar',
|
'foo': 'bar',
|
||||||
}, [ip_address_processor])
|
}, [ip_address_processor])
|
||||||
|
|
||||||
|
Note::
|
||||||
|
If you are using Django's ``render_to_response()`` shortcut to populate a
|
||||||
|
template with the contents of a dictionary, your template will be passed a
|
||||||
|
``Context`` instance by default (not a ``RequestContext``). If you wish to
|
||||||
|
use a ``RequestContext`` in your template rendering, you need to pass an
|
||||||
|
optional third argument to ``render_to_response()``: a ``RequestContext``
|
||||||
|
instance. Your code might look like this::
|
||||||
|
|
||||||
|
def some_view(request):
|
||||||
|
# ...
|
||||||
|
return render_to_response('my_template'html',
|
||||||
|
my_data_dictionary,
|
||||||
|
context_instance = RequestContext(request))
|
||||||
|
|
||||||
Here's what each of the default processors does:
|
Here's what each of the default processors does:
|
||||||
|
|
||||||
.. _HttpRequest object: http://www.djangoproject.com/documentation/request_response/#httprequest-objects
|
.. _HttpRequest object: http://www.djangoproject.com/documentation/request_response/#httprequest-objects
|
||||||
@ -366,6 +395,18 @@ If ``TEMPLATE_CONTEXT_PROCESSORS`` contains this processor, every
|
|||||||
`HttpRequest object`_. Note that this processor is not enabled by default;
|
`HttpRequest object`_. Note that this processor is not enabled by default;
|
||||||
you'll have to activate it.
|
you'll have to activate it.
|
||||||
|
|
||||||
|
Writing your own context processors
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
A context processor has a very simple interface: It's just a Python function
|
||||||
|
that takes one argument, an ``HttpRequest`` object, and returns a dictionary
|
||||||
|
that gets added to the template context. Each context processor *must* return
|
||||||
|
a dictionary.
|
||||||
|
|
||||||
|
Custom context processors can live anywhere in your code base. All Django cares
|
||||||
|
about is that your custom context processors are pointed-to by your
|
||||||
|
``TEMPLATE_CONTEXT_PROCESSORS`` setting.
|
||||||
|
|
||||||
Loading templates
|
Loading templates
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
@ -805,7 +846,7 @@ Inclusion tags
|
|||||||
|
|
||||||
Another common type of template tag is the type that displays some data by
|
Another common type of template tag is the type that displays some data by
|
||||||
rendering *another* template. For example, Django's admin interface uses custom
|
rendering *another* template. For example, Django's admin interface uses custom
|
||||||
template tags to display the buttons along the botton of the "add/change" form
|
template tags to display the buttons along the bottom of the "add/change" form
|
||||||
pages. Those buttons always look the same, but the link targets change depending
|
pages. Those buttons always look the same, but the link targets change depending
|
||||||
on the object being edited -- so they're a perfect case for using a small
|
on the object being edited -- so they're a perfect case for using a small
|
||||||
template that is filled with details from the current object. (In the admin's
|
template that is filled with details from the current object. (In the admin's
|
||||||
|
@ -389,7 +389,7 @@ an alternative framework as if they were normal Django tests.
|
|||||||
|
|
||||||
When you run ``./manage.py test``, Django looks at the ``TEST_RUNNER``
|
When you run ``./manage.py test``, Django looks at the ``TEST_RUNNER``
|
||||||
setting to determine what to do. By default, ``TEST_RUNNER`` points to ``django.test.simple.run_tests``. This method defines the default Django
|
setting to determine what to do. By default, ``TEST_RUNNER`` points to ``django.test.simple.run_tests``. This method defines the default Django
|
||||||
testing behaviour. This behaviour involves:
|
testing behavior. This behavior involves:
|
||||||
|
|
||||||
#. Performing global pre-test setup
|
#. Performing global pre-test setup
|
||||||
#. Creating the test database
|
#. Creating the test database
|
||||||
@ -435,7 +435,7 @@ a number of utility methods in the ``django.test.utils`` module.
|
|||||||
``create_test_db(verbosity=1, autoclobber=False)``
|
``create_test_db(verbosity=1, autoclobber=False)``
|
||||||
Creates a new test database, and run ``syncdb`` against it.
|
Creates a new test database, and run ``syncdb`` against it.
|
||||||
|
|
||||||
``verbosity`` has the same behaviour as in the test runner.
|
``verbosity`` has the same behavior as in the test runner.
|
||||||
|
|
||||||
``Autoclobber`` describes the behavior that will occur if a database with
|
``Autoclobber`` describes the behavior that will occur if a database with
|
||||||
the same name as the test database is discovered. If ``autoclobber`` is False,
|
the same name as the test database is discovered. If ``autoclobber`` is False,
|
||||||
@ -450,4 +450,4 @@ a number of utility methods in the ``django.test.utils`` module.
|
|||||||
Destroys the database with the name ``settings.DATABASE_NAME`` matching,
|
Destroys the database with the name ``settings.DATABASE_NAME`` matching,
|
||||||
and restores the value of ``settings.DATABASE_NAME`` to the provided name.
|
and restores the value of ``settings.DATABASE_NAME`` to the provided name.
|
||||||
|
|
||||||
``verbosity`` has the same behaviour as in the test runner.
|
``verbosity`` has the same behavior as in the test runner.
|
||||||
|
@ -377,7 +377,7 @@ By default, ``TEMPLATE_DIRS`` is empty. So, let's add a line to it, to tell
|
|||||||
Django where our templates live::
|
Django where our templates live::
|
||||||
|
|
||||||
TEMPLATE_DIRS = (
|
TEMPLATE_DIRS = (
|
||||||
"/home/mytemplates", # Change this to your own directory.
|
"/home/my_username/mytemplates", # Change this to your own directory.
|
||||||
)
|
)
|
||||||
|
|
||||||
Now copy the template ``admin/base_site.html`` from within the default Django
|
Now copy the template ``admin/base_site.html`` from within the default Django
|
||||||
|
@ -91,7 +91,7 @@ Finally, it calls that ``detail()`` function like so::
|
|||||||
The ``poll_id='23'`` part comes from ``(?P<poll_id>\d+)``. Using parenthesis around a
|
The ``poll_id='23'`` part comes from ``(?P<poll_id>\d+)``. Using parenthesis around a
|
||||||
pattern "captures" the text matched by that pattern and sends it as an argument
|
pattern "captures" the text matched by that pattern and sends it as an argument
|
||||||
to the view function; the ``?P<poll_id>`` defines the name that will be used to
|
to the view function; the ``?P<poll_id>`` defines the name that will be used to
|
||||||
identify the matched pattern; and ``\d+`` is a regular experession to match a sequence of
|
identify the matched pattern; and ``\d+`` is a regular expression to match a sequence of
|
||||||
digits (i.e., a number).
|
digits (i.e., a number).
|
||||||
|
|
||||||
Because the URL patterns are regular expressions, there really is no limit on
|
Because the URL patterns are regular expressions, there really is no limit on
|
||||||
@ -257,7 +257,7 @@ provides a shortcut. Here's the full ``index()`` view, rewritten::
|
|||||||
from mysite.polls.models import Poll
|
from mysite.polls.models import Poll
|
||||||
|
|
||||||
def index(request):
|
def index(request):
|
||||||
latest_poll_list = Poll.objects.all().order_by('-pub_date')
|
latest_poll_list = Poll.objects.all().order_by('-pub_date')[:5]
|
||||||
return render_to_response('polls/index.html', {'latest_poll_list': latest_poll_list})
|
return render_to_response('polls/index.html', {'latest_poll_list': latest_poll_list})
|
||||||
|
|
||||||
Note that we no longer need to import ``loader``, ``Context`` or
|
Note that we no longer need to import ``loader``, ``Context`` or
|
||||||
|
@ -207,7 +207,7 @@ for the polls app, we manually specify a template name for the results view:
|
|||||||
template. Note that we use ``dict()`` to return an altered dictionary in place.
|
template. Note that we use ``dict()`` to return an altered dictionary in place.
|
||||||
|
|
||||||
In previous parts of the tutorial, the templates have been provided with a context
|
In previous parts of the tutorial, the templates have been provided with a context
|
||||||
that contains the ``poll` and ``latest_poll_list`` context variables. However,
|
that contains the ``poll`` and ``latest_poll_list`` context variables. However,
|
||||||
the generic views provide the variables ``object`` and ``object_list`` as context.
|
the generic views provide the variables ``object`` and ``object_list`` as context.
|
||||||
Therefore, you need to change your templates to match the new context variables.
|
Therefore, you need to change your templates to match the new context variables.
|
||||||
Go through your templates, and modify any reference to ``latest_poll_list`` to
|
Go through your templates, and modify any reference to ``latest_poll_list`` to
|
||||||
|
217
ez_setup.py
217
ez_setup.py
@ -1,217 +0,0 @@
|
|||||||
#!python
|
|
||||||
"""Bootstrap setuptools installation
|
|
||||||
|
|
||||||
If you want to use setuptools in your package's setup.py, just include this
|
|
||||||
file in the same directory with it, and add this to the top of your setup.py::
|
|
||||||
|
|
||||||
from ez_setup import use_setuptools
|
|
||||||
use_setuptools()
|
|
||||||
|
|
||||||
If you want to require a specific version of setuptools, set a download
|
|
||||||
mirror, or use an alternate download directory, you can do so by supplying
|
|
||||||
the appropriate options to ``use_setuptools()``.
|
|
||||||
|
|
||||||
This file can also be run as a script to install or upgrade setuptools.
|
|
||||||
"""
|
|
||||||
import sys
|
|
||||||
DEFAULT_VERSION = "0.6c1"
|
|
||||||
DEFAULT_URL = "http://cheeseshop.python.org/packages/%s/s/setuptools/" % sys.version[:3]
|
|
||||||
|
|
||||||
md5_data = {
|
|
||||||
'setuptools-0.6b1-py2.3.egg': '8822caf901250d848b996b7f25c6e6ca',
|
|
||||||
'setuptools-0.6b1-py2.4.egg': 'b79a8a403e4502fbb85ee3f1941735cb',
|
|
||||||
'setuptools-0.6b2-py2.3.egg': '5657759d8a6d8fc44070a9d07272d99b',
|
|
||||||
'setuptools-0.6b2-py2.4.egg': '4996a8d169d2be661fa32a6e52e4f82a',
|
|
||||||
'setuptools-0.6b3-py2.3.egg': 'bb31c0fc7399a63579975cad9f5a0618',
|
|
||||||
'setuptools-0.6b3-py2.4.egg': '38a8c6b3d6ecd22247f179f7da669fac',
|
|
||||||
'setuptools-0.6b4-py2.3.egg': '62045a24ed4e1ebc77fe039aa4e6f7e5',
|
|
||||||
'setuptools-0.6b4-py2.4.egg': '4cb2a185d228dacffb2d17f103b3b1c4',
|
|
||||||
'setuptools-0.6c1-py2.3.egg': 'b3f2b5539d65cb7f74ad79127f1a908c',
|
|
||||||
'setuptools-0.6c1-py2.4.egg': 'b45adeda0667d2d2ffe14009364f2a4b',
|
|
||||||
}
|
|
||||||
|
|
||||||
import sys, os
|
|
||||||
|
|
||||||
def _validate_md5(egg_name, data):
|
|
||||||
if egg_name in md5_data:
|
|
||||||
from md5 import md5
|
|
||||||
digest = md5(data).hexdigest()
|
|
||||||
if digest != md5_data[egg_name]:
|
|
||||||
print >>sys.stderr, (
|
|
||||||
"md5 validation of %s failed! (Possible download problem?)"
|
|
||||||
% egg_name
|
|
||||||
)
|
|
||||||
sys.exit(2)
|
|
||||||
return data
|
|
||||||
|
|
||||||
|
|
||||||
def use_setuptools(
|
|
||||||
version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
|
|
||||||
download_delay=15
|
|
||||||
):
|
|
||||||
"""Automatically find/download setuptools and make it available on sys.path
|
|
||||||
|
|
||||||
`version` should be a valid setuptools version number that is available
|
|
||||||
as an egg for download under the `download_base` URL (which should end with
|
|
||||||
a '/'). `to_dir` is the directory where setuptools will be downloaded, if
|
|
||||||
it is not already available. If `download_delay` is specified, it should
|
|
||||||
be the number of seconds that will be paused before initiating a download,
|
|
||||||
should one be required. If an older version of setuptools is installed,
|
|
||||||
this routine will print a message to ``sys.stderr`` and raise SystemExit in
|
|
||||||
an attempt to abort the calling script.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
import setuptools
|
|
||||||
if setuptools.__version__ == '0.0.1':
|
|
||||||
print >>sys.stderr, (
|
|
||||||
"You have an obsolete version of setuptools installed. Please\n"
|
|
||||||
"remove it from your system entirely before rerunning this script."
|
|
||||||
)
|
|
||||||
sys.exit(2)
|
|
||||||
except ImportError:
|
|
||||||
egg = download_setuptools(version, download_base, to_dir, download_delay)
|
|
||||||
sys.path.insert(0, egg)
|
|
||||||
import setuptools; setuptools.bootstrap_install_from = egg
|
|
||||||
|
|
||||||
import pkg_resources
|
|
||||||
try:
|
|
||||||
pkg_resources.require("setuptools>="+version)
|
|
||||||
|
|
||||||
except pkg_resources.VersionConflict:
|
|
||||||
# XXX could we install in a subprocess here?
|
|
||||||
print >>sys.stderr, (
|
|
||||||
"The required version of setuptools (>=%s) is not available, and\n"
|
|
||||||
"can't be installed while this script is running. Please install\n"
|
|
||||||
" a more recent version first."
|
|
||||||
) % version
|
|
||||||
sys.exit(2)
|
|
||||||
|
|
||||||
def download_setuptools(
|
|
||||||
version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
|
|
||||||
delay = 15
|
|
||||||
):
|
|
||||||
"""Download setuptools from a specified location and return its filename
|
|
||||||
|
|
||||||
`version` should be a valid setuptools version number that is available
|
|
||||||
as an egg for download under the `download_base` URL (which should end
|
|
||||||
with a '/'). `to_dir` is the directory where the egg will be downloaded.
|
|
||||||
`delay` is the number of seconds to pause before an actual download attempt.
|
|
||||||
"""
|
|
||||||
import urllib2, shutil
|
|
||||||
egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3])
|
|
||||||
url = download_base + egg_name
|
|
||||||
saveto = os.path.join(to_dir, egg_name)
|
|
||||||
src = dst = None
|
|
||||||
if not os.path.exists(saveto): # Avoid repeated downloads
|
|
||||||
try:
|
|
||||||
from distutils import log
|
|
||||||
if delay:
|
|
||||||
log.warn("""
|
|
||||||
---------------------------------------------------------------------------
|
|
||||||
This script requires setuptools version %s to run (even to display
|
|
||||||
help). I will attempt to download it for you (from
|
|
||||||
%s), but
|
|
||||||
you may need to enable firewall access for this script first.
|
|
||||||
I will start the download in %d seconds.
|
|
||||||
|
|
||||||
(Note: if this machine does not have network access, please obtain the file
|
|
||||||
|
|
||||||
%s
|
|
||||||
|
|
||||||
and place it in this directory before rerunning this script.)
|
|
||||||
---------------------------------------------------------------------------""",
|
|
||||||
version, download_base, delay, url
|
|
||||||
); from time import sleep; sleep(delay)
|
|
||||||
log.warn("Downloading %s", url)
|
|
||||||
src = urllib2.urlopen(url)
|
|
||||||
# Read/write all in one block, so we don't create a corrupt file
|
|
||||||
# if the download is interrupted.
|
|
||||||
data = _validate_md5(egg_name, src.read())
|
|
||||||
dst = open(saveto,"wb"); dst.write(data)
|
|
||||||
finally:
|
|
||||||
if src: src.close()
|
|
||||||
if dst: dst.close()
|
|
||||||
return os.path.realpath(saveto)
|
|
||||||
|
|
||||||
def main(argv, version=DEFAULT_VERSION):
|
|
||||||
"""Install or upgrade setuptools and EasyInstall"""
|
|
||||||
|
|
||||||
try:
|
|
||||||
import setuptools
|
|
||||||
except ImportError:
|
|
||||||
import tempfile, shutil
|
|
||||||
tmpdir = tempfile.mkdtemp(prefix="easy_install-")
|
|
||||||
try:
|
|
||||||
egg = download_setuptools(version, to_dir=tmpdir, delay=0)
|
|
||||||
sys.path.insert(0,egg)
|
|
||||||
from setuptools.command.easy_install import main
|
|
||||||
return main(list(argv)+[egg]) # we're done here
|
|
||||||
finally:
|
|
||||||
shutil.rmtree(tmpdir)
|
|
||||||
else:
|
|
||||||
if setuptools.__version__ == '0.0.1':
|
|
||||||
# tell the user to uninstall obsolete version
|
|
||||||
use_setuptools(version)
|
|
||||||
|
|
||||||
req = "setuptools>="+version
|
|
||||||
import pkg_resources
|
|
||||||
try:
|
|
||||||
pkg_resources.require(req)
|
|
||||||
except pkg_resources.VersionConflict:
|
|
||||||
try:
|
|
||||||
from setuptools.command.easy_install import main
|
|
||||||
except ImportError:
|
|
||||||
from easy_install import main
|
|
||||||
main(list(argv)+[download_setuptools(delay=0)])
|
|
||||||
sys.exit(0) # try to force an exit
|
|
||||||
else:
|
|
||||||
if argv:
|
|
||||||
from setuptools.command.easy_install import main
|
|
||||||
main(argv)
|
|
||||||
else:
|
|
||||||
print "Setuptools version",version,"or greater has been installed."
|
|
||||||
print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)'
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def update_md5(filenames):
|
|
||||||
"""Update our built-in md5 registry"""
|
|
||||||
|
|
||||||
import re
|
|
||||||
from md5 import md5
|
|
||||||
|
|
||||||
for name in filenames:
|
|
||||||
base = os.path.basename(name)
|
|
||||||
f = open(name,'rb')
|
|
||||||
md5_data[base] = md5(f.read()).hexdigest()
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
data = [" %r: %r,\n" % it for it in md5_data.items()]
|
|
||||||
data.sort()
|
|
||||||
repl = "".join(data)
|
|
||||||
|
|
||||||
import inspect
|
|
||||||
srcfile = inspect.getsourcefile(sys.modules[__name__])
|
|
||||||
f = open(srcfile, 'rb'); src = f.read(); f.close()
|
|
||||||
|
|
||||||
match = re.search("\nmd5_data = {\n([^}]+)}", src)
|
|
||||||
if not match:
|
|
||||||
print >>sys.stderr, "Internal error!"
|
|
||||||
sys.exit(2)
|
|
||||||
|
|
||||||
src = src[:match.start(1)] + repl + src[match.end(1):]
|
|
||||||
f = open(srcfile,'w')
|
|
||||||
f.write(src)
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__=='__main__':
|
|
||||||
if len(sys.argv)>2 and sys.argv[1]=='--md5update':
|
|
||||||
update_md5(sys.argv[2:])
|
|
||||||
else:
|
|
||||||
main(sys.argv[1:])
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
45
setup.py
45
setup.py
@ -1,7 +1,25 @@
|
|||||||
import ez_setup # From http://peak.telecommunity.com/DevCenter/setuptools
|
from distutils.core import setup
|
||||||
ez_setup.use_setuptools()
|
from distutils.command.install import INSTALL_SCHEMES
|
||||||
|
import os
|
||||||
|
|
||||||
from setuptools import setup, find_packages
|
# Tell distutils to put the data_files in platform-specific installation
|
||||||
|
# locations. See here for an explanation:
|
||||||
|
# http://groups.google.com/group/comp.lang.python/browse_thread/thread/35ec7b2fed36eaec/2105ee4d9e8042cb
|
||||||
|
for scheme in INSTALL_SCHEMES.values():
|
||||||
|
scheme['data'] = scheme['purelib']
|
||||||
|
|
||||||
|
# Compile the list of packages available, because distutils doesn't have
|
||||||
|
# an easy way to do this.
|
||||||
|
packages, data_files = [], []
|
||||||
|
root_dir = os.path.join(os.path.dirname(__file__), 'django')
|
||||||
|
for dirpath, dirnames, filenames in os.walk(root_dir):
|
||||||
|
# Ignore dirnames that start with '.'
|
||||||
|
for i, dirname in enumerate(dirnames):
|
||||||
|
if dirname.startswith('.'): del dirnames[i]
|
||||||
|
if '__init__.py' in filenames:
|
||||||
|
packages.append(dirpath.replace('/', '.'))
|
||||||
|
else:
|
||||||
|
data_files.append((dirpath, [os.path.join(dirpath, f) for f in filenames]))
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name = "Django",
|
name = "Django",
|
||||||
@ -10,24 +28,7 @@ setup(
|
|||||||
author = 'Lawrence Journal-World',
|
author = 'Lawrence Journal-World',
|
||||||
author_email = 'holovaty@gmail.com',
|
author_email = 'holovaty@gmail.com',
|
||||||
description = 'A high-level Python Web framework that encourages rapid development and clean, pragmatic design.',
|
description = 'A high-level Python Web framework that encourages rapid development and clean, pragmatic design.',
|
||||||
license = 'BSD',
|
packages = packages,
|
||||||
packages = find_packages(exclude=['examples', 'examples.*']),
|
data_files = data_files,
|
||||||
package_data = {
|
|
||||||
'': ['*.TXT'],
|
|
||||||
'django.conf': ['locale/*/LC_MESSAGES/*'],
|
|
||||||
'django.contrib.admin': ['templates/admin/*.html',
|
|
||||||
'templates/admin/auth/user/*.html',
|
|
||||||
'templates/admin_doc/*.html',
|
|
||||||
'templates/registration/*.html',
|
|
||||||
'templates/widget/*.html',
|
|
||||||
'media/css/*.css',
|
|
||||||
'media/img/admin/*.gif',
|
|
||||||
'media/img/admin/*.png',
|
|
||||||
'media/js/*.js',
|
|
||||||
'media/js/admin/*js'],
|
|
||||||
'django.contrib.comments': ['templates/comments/*.html'],
|
|
||||||
'django.contrib.sitemaps': ['templates/*.xml'],
|
|
||||||
},
|
|
||||||
scripts = ['django/bin/django-admin.py'],
|
scripts = ['django/bin/django-admin.py'],
|
||||||
zip_safe = False,
|
|
||||||
)
|
)
|
||||||
|
@ -30,6 +30,14 @@ class Waiter(models.Model):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "%s the waiter at %s" % (self.name, self.restaurant)
|
return "%s the waiter at %s" % (self.name, self.restaurant)
|
||||||
|
|
||||||
|
class ManualPrimaryKey(models.Model):
|
||||||
|
primary_key = models.CharField(maxlength=10, primary_key=True)
|
||||||
|
name = models.CharField(maxlength = 50)
|
||||||
|
|
||||||
|
class RelatedModel(models.Model):
|
||||||
|
link = models.OneToOneField(ManualPrimaryKey)
|
||||||
|
name = models.CharField(maxlength = 50)
|
||||||
|
|
||||||
__test__ = {'API_TESTS':"""
|
__test__ = {'API_TESTS':"""
|
||||||
# Create a couple of Places.
|
# Create a couple of Places.
|
||||||
>>> p1 = Place(name='Demon Dogs', address='944 W. Fullerton')
|
>>> p1 = Place(name='Demon Dogs', address='944 W. Fullerton')
|
||||||
@ -151,4 +159,10 @@ DoesNotExist: Restaurant matching query does not exist.
|
|||||||
# Delete the restaurant; the waiter should also be removed
|
# Delete the restaurant; the waiter should also be removed
|
||||||
>>> r = Restaurant.objects.get(pk=1)
|
>>> r = Restaurant.objects.get(pk=1)
|
||||||
>>> r.delete()
|
>>> r.delete()
|
||||||
|
|
||||||
|
# One-to-one fields still work if you create your own primary key
|
||||||
|
>>> o1 = ManualPrimaryKey(primary_key="abc123", name="primary")
|
||||||
|
>>> o1.save()
|
||||||
|
>>> o2 = RelatedModel(link=o1, name="secondary")
|
||||||
|
>>> o2.save()
|
||||||
"""}
|
"""}
|
||||||
|
@ -21,22 +21,22 @@ r"""
|
|||||||
'7'
|
'7'
|
||||||
>>> format(my_birthday, 'N')
|
>>> format(my_birthday, 'N')
|
||||||
'July'
|
'July'
|
||||||
>>> format(my_birthday, 'O')
|
>>> no_tz or format(my_birthday, 'O') == '+0100'
|
||||||
'+0100'
|
True
|
||||||
>>> format(my_birthday, 'P')
|
>>> format(my_birthday, 'P')
|
||||||
'10 p.m.'
|
'10 p.m.'
|
||||||
>>> format(my_birthday, 'r')
|
>>> no_tz or format(my_birthday, 'r') == 'Sun, 8 Jul 1979 22:00:00 +0100'
|
||||||
'Sun, 8 Jul 1979 22:00:00 +0100'
|
True
|
||||||
>>> format(my_birthday, 's')
|
>>> format(my_birthday, 's')
|
||||||
'00'
|
'00'
|
||||||
>>> format(my_birthday, 'S')
|
>>> format(my_birthday, 'S')
|
||||||
'th'
|
'th'
|
||||||
>>> format(my_birthday, 't')
|
>>> format(my_birthday, 't')
|
||||||
'31'
|
'31'
|
||||||
>>> format(my_birthday, 'T')
|
>>> no_tz or format(my_birthday, 'T') == 'CET'
|
||||||
'CET'
|
True
|
||||||
>>> format(my_birthday, 'U')
|
>>> no_tz or format(my_birthday, 'U') == '300531600'
|
||||||
'300531600'
|
True
|
||||||
>>> format(my_birthday, 'w')
|
>>> format(my_birthday, 'w')
|
||||||
'0'
|
'0'
|
||||||
>>> format(my_birthday, 'W')
|
>>> format(my_birthday, 'W')
|
||||||
@ -47,17 +47,17 @@ r"""
|
|||||||
'1979'
|
'1979'
|
||||||
>>> format(my_birthday, 'z')
|
>>> format(my_birthday, 'z')
|
||||||
'189'
|
'189'
|
||||||
>>> format(my_birthday, 'Z')
|
>>> no_tz or format(my_birthday, 'Z') == '3600'
|
||||||
'3600'
|
True
|
||||||
|
|
||||||
>>> format(summertime, 'I')
|
>>> no_tz or format(summertime, 'I') == '1'
|
||||||
'1'
|
True
|
||||||
>>> format(summertime, 'O')
|
>>> no_tz or format(summertime, 'O') == '+0200'
|
||||||
'+0200'
|
True
|
||||||
>>> format(wintertime, 'I')
|
>>> no_tz or format(wintertime, 'I') == '0'
|
||||||
'0'
|
True
|
||||||
>>> format(wintertime, 'O')
|
>>> no_tz or format(wintertime, 'O') == '+0100'
|
||||||
'+0100'
|
True
|
||||||
|
|
||||||
>>> format(my_birthday, r'Y z \C\E\T')
|
>>> format(my_birthday, r'Y z \C\E\T')
|
||||||
'1979 189 CET'
|
'1979 189 CET'
|
||||||
@ -73,7 +73,11 @@ format = dateformat.format
|
|||||||
os.environ['TZ'] = 'Europe/Copenhagen'
|
os.environ['TZ'] = 'Europe/Copenhagen'
|
||||||
translation.activate('en-us')
|
translation.activate('en-us')
|
||||||
|
|
||||||
time.tzset()
|
try:
|
||||||
|
time.tzset()
|
||||||
|
no_tz = False
|
||||||
|
except AttributeError:
|
||||||
|
no_tz = True
|
||||||
|
|
||||||
my_birthday = datetime.datetime(1979, 7, 8, 22, 00)
|
my_birthday = datetime.datetime(1979, 7, 8, 22, 00)
|
||||||
summertime = datetime.datetime(2005, 10, 30, 1, 00)
|
summertime = datetime.datetime(2005, 10, 30, 1, 00)
|
||||||
|
0
tests/regressiontests/null_queries/__init__.py
Normal file
0
tests/regressiontests/null_queries/__init__.py
Normal file
54
tests/regressiontests/null_queries/models.py
Normal file
54
tests/regressiontests/null_queries/models.py
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
from django.db import models
|
||||||
|
|
||||||
|
class Poll(models.Model):
|
||||||
|
question = models.CharField(maxlength=200)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "Q: %s " % self.question
|
||||||
|
|
||||||
|
class Choice(models.Model):
|
||||||
|
poll = models.ForeignKey(Poll)
|
||||||
|
choice = models.CharField(maxlength=200)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "Choice: %s in poll %s" % (self.choice, self.poll)
|
||||||
|
|
||||||
|
__test__ = {'API_TESTS':"""
|
||||||
|
# Regression test for the use of None as a query value. None is interpreted as
|
||||||
|
# an SQL NULL, but only in __exact queries.
|
||||||
|
# Set up some initial polls and choices
|
||||||
|
>>> p1 = Poll(question='Why?')
|
||||||
|
>>> p1.save()
|
||||||
|
>>> c1 = Choice(poll=p1, choice='Because.')
|
||||||
|
>>> c1.save()
|
||||||
|
>>> c2 = Choice(poll=p1, choice='Why Not?')
|
||||||
|
>>> c2.save()
|
||||||
|
|
||||||
|
# Exact query with value None returns nothing (=NULL in sql)
|
||||||
|
>>> Choice.objects.filter(id__exact=None)
|
||||||
|
[]
|
||||||
|
|
||||||
|
# Valid query, but fails because foo isn't a keyword
|
||||||
|
>>> Choice.objects.filter(foo__exact=None)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
TypeError: Cannot resolve keyword 'foo' into field
|
||||||
|
|
||||||
|
# Can't use None on anything other than __exact
|
||||||
|
>>> Choice.objects.filter(id__gt=None)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: Cannot use None as a query value
|
||||||
|
|
||||||
|
# Can't use None on anything other than __exact
|
||||||
|
>>> Choice.objects.filter(foo__gt=None)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: Cannot use None as a query value
|
||||||
|
|
||||||
|
# Related managers use __exact=None implicitly if the object hasn't been saved.
|
||||||
|
>>> p2 = Poll(question="How?")
|
||||||
|
>>> p2.choice_set.all()
|
||||||
|
[]
|
||||||
|
|
||||||
|
"""}
|
@ -170,6 +170,9 @@ class Templates(unittest.TestCase):
|
|||||||
# Escaped backslash using known escape char
|
# Escaped backslash using known escape char
|
||||||
'basic-syntax35': (r'{{ var|default_if_none:"foo\now" }}', {"var": None}, r'foo\now'),
|
'basic-syntax35': (r'{{ var|default_if_none:"foo\now" }}', {"var": None}, r'foo\now'),
|
||||||
|
|
||||||
|
# Empty strings can be passed as arguments to filters
|
||||||
|
'basic-syntax36': (r'{{ var|join:"" }}', {'var': ['a', 'b', 'c']}, 'abc'),
|
||||||
|
|
||||||
### COMMENT TAG ###########################################################
|
### COMMENT TAG ###########################################################
|
||||||
'comment-tag01': ("{% comment %}this is hidden{% endcomment %}hello", {}, "hello"),
|
'comment-tag01': ("{% comment %}this is hidden{% endcomment %}hello", {}, "hello"),
|
||||||
'comment-tag02': ("{% comment %}this is hidden{% endcomment %}hello{% comment %}foo{% endcomment %}", {}, "hello"),
|
'comment-tag02': ("{% comment %}this is hidden{% endcomment %}hello{% comment %}foo{% endcomment %}", {}, "hello"),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user